vb.net指数超出范围。必须是非负数且小于集合

时间:2017-05-03 22:31:20

标签: excel vb.net indexing datagridview

我目前有一个datagridview,它使用以下代码插入图像;

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim opf As New OpenFileDialog
    opf.Filter = "Choose Image(*.jpg;*.png;*.gif)|*.jpg;*.png;*.gif"

    If opf.ShowDialog = DialogResult.OK Then
        PictureBox1.Image = Image.FromFile(opf.FileName)
    End If
    Try
        Dim ms As New MemoryStream
        PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
        Dim img As Byte()
        img = ms.ToArray()
        DataGridView1.Rows.Add(img)
    Catch ex As Exception
        MessageBox.Show(ex.Message.ToString())
    End Try
End Sub

点击并选择它在datagridview1中显示的图片。

使用以下代码继续并单击button2时,我将获得错误;

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    'Save to excel with headers
    Dim ExcelApp As Object, ExcelBook As Object
    Dim ExcelSheet As Object
    Dim i As Integer
    Dim j As Integer

    'create object of excel
    ExcelApp = CreateObject("Excel.Application")
    ExcelBook = ExcelApp.WorkBooks.Add
    ExcelSheet = ExcelBook.WorkSheets(1)

    With ExcelSheet
        For Each column As DataGridViewColumn In DataGridView1.Columns
            .cells(1, column.Index + 1) = column.HeaderText
        Next
        For i = 1 To Me.DataGridView1.RowCount
            .cells(i + 1, 1) = Me.DataGridView1.Rows(i - 1).Cells(i).Value
            For j = 1 To DataGridView1.Columns.Count - 1
                .cells(i + 1, j + 1) = DataGridView1.Rows(i - 1).Cells(j).Value
            Next
            Dim formatRange As Excel.Range
            formatRange = ExcelSheet.Range("A1")
            formatRange.EntireRow.Font.Bold = True
            formatRange = ExcelSheet.Range("A1", "A1")
            formatRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue)
            formatRange.BorderAround(Excel.XlLineStyle.xlContinuous)
            formatRange = ExcelSheet.Range("a1", "A1")
            formatRange.EntireRow.BorderAround()
        Next
    End With

    ExcelApp.Visible = True
    '
    ExcelSheet = Nothing
    ExcelBook = Nothing
    ExcelApp = Nothing
    Application.Exit()
    End
End Sub

表单本身具有以下代码;

'  Create Datagridview image column
    Dim dgvImageColumn As New DataGridViewImageColumn
    DataGridView1.Columns.Add(dgvImageColumn)
    dgvImageColumn.ImageLayout = DataGridViewImageCellLayout.Stretch
    Dim dgvTextColumn As New DataGridViewTextBoxColumn
    DataGridView1.Columns(0).Name = "Image"


    DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
    DataGridView1.RowTemplate.Height = 120
    DataGridView1.AllowUserToAddRows = False

当我点击继续保存到Excel时,它会给我以下错误;

mscorlib.dll中出现未处理的“System.ArgumentOutOfRangeException”类型异常

其他信息:指数超出范围。必须是非负数且小于集合的大小。

它引用的行如下;

.cells(i + 1, 1) = Me.DataGridView1.Rows(i - 1).Cells(i).Value

有关如何克服此问题的任何建议?

感谢任何支持

*添加到DATAGRIDVIEW的图片

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim opf As New OpenFileDialog
    opf.Filter = "Choose Image(*.jpg;*.png;*.gif)|*.jpg;*.png;*.gif"

    If opf.ShowDialog = DialogResult.OK Then
        PictureBox1.Image = Image.FromFile(opf.FileName)
    End If
    Try
        Dim ms As New MemoryStream
        PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
        Dim img As Byte()
        img = ms.ToArray()
        DataGridView1.Rows.Add(img)
    Catch ex As Exception
        MessageBox.Show(ex.Message.ToString())
    End Try
End Sub

2 个答案:

答案 0 :(得分:0)

您正在使索引更加复杂。在DataGridView中使用excel中的不同行索引来处理不同的行索引会使事情变得复杂。尝试下面的简化版本,它应该按预期工作。

With ExcelSheet
  For Each column As DataGridViewColumn In DataGridView1.Columns
    .cells(1, column.Index + 1) = column.HeaderText
  Next
  Dim excelRowIndex = 2
  For Each row As DataGridViewRow In DataGridView1.Rows
    For j = 0 To DataGridView1.Columns.Count - 1
      .cells(excelRowIndex, j + 1) = row.Cells(j).Value
    Next
    excelRowIndex += 1
  Next
  Dim formatRange As Excel.Range
  formatRange = ExcelSheet.Range("A1")
  formatRange.EntireRow.Font.Bold = True
  formatRange = ExcelSheet.Range("A1", "A1")
  formatRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue)
  formatRange.BorderAround(Excel.XlLineStyle.xlContinuous)
  formatRange = ExcelSheet.Range("a1", "A1")
  formatRange.EntireRow.BorderAround()
End With

编辑以评论错误

我确信您收到此错误是因为您尝试(错误地)插入到下面一行的Excel工作表单元格中的图像/图片。

.cells(excelRowIndex, j + 1) = row.Cells(j).Value

首先......你不能在excel“Cell”中添加“图像/图片”。您可以将具有图像的形状添加到工作表中。您还可以使用图片属性将图片相对于某个单元格移动,但是,再次...您不能像使用datagridview那样“直接”将图像添加到Excel单元格。因此,如果网格单元格中的值是图像,则上面的行将崩溃。

其次,可能是考虑使用另一个excel库的一个很好的理由,遗憾的是Excel互操作库没有通过传递一个“Image”对象来添加图片/图像的方法(至少我知道的)。您可以从字符串路径添加形状/图像,但如果您已经拥有该图像(就像您一样),则必须将其保存到文件中才能将图像传递给Excel。这意味着,您必须按照刚刚描述的方式保存文件,或保留/保存每个图像单元格路径。有一篇文章演示如何使用剪贴板执行此操作并粘贴以插入图像而不使用文件路径... How to insert picture from resources to Excel sheet, using VB2010

上述两种方法似乎都不可取,遗憾的是如果你必须使用互操作,那么你可能别无选择。我的理解是有更好的开源库,这个问题可能是它们存在的原因之一。

最后,无论您选择使用哪个库,放置图片形状都需要额外注意,因为正如我上面所解释的那样,您不能像使用DataGridView单元格那样简单地将图片添加到工作表单元格中。这肯定会涉及跟踪工作表中图片形状的位置,确保其保持可见并保留其相关数据。

下面更新的代码在第0列中有一个Image列。导出此列时,由于我没有跟踪用户可能选择的图像路径,因此代码只输出相同的图像。它将图像放入工作表中:picXpicY变量定义图片的左上角。每个新图片简单地向下移动10个像素。如果要删除行等,您需要应用逻辑来告诉形状/图片哪个单元格保持不变...只是一点,希望它有所帮助。

With ExcelSheet
  For Each column As DataGridViewColumn In DataGridView1.Columns
    .cells(1, column.Index + 1) = column.HeaderText
  Next
  Dim excelRowIndex = 2
  Dim picX = 50
  Dim picY = 50
  For Each row As DataGridViewRow In DataGridView1.Rows
    For j = 0 To DataGridView1.Columns.Count - 1
      If (j = 0) Then
        .Shapes.AddPicture("D:\Test\TestImage.jpg", Microsoft.Office.Core.MsoTriState.msoFalse,
                           Microsoft.Office.Core.MsoTriState.msoCTrue, picX, picY, 200, 45)
        picX += 10
        picY += 10
      Else
        .cells(excelRowIndex, j + 1) = row.Cells(j).Value
      End If
    Next
    excelRowIndex += 1
  Next
  Dim formatRange As Excel.Range
  formatRange = ExcelSheet.Range("A1")
  formatRange.EntireRow.Font.Bold = True
  formatRange = ExcelSheet.Range("A1", "A1")
  formatRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue)
  formatRange.BorderAround(Excel.XlLineStyle.xlContinuous)
  formatRange = ExcelSheet.Range("a1", "A1")
  formatRange.EntireRow.BorderAround()
End With

答案 1 :(得分:0)

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    'Save to excel with headers
    Dim ExcelApp As Object, ExcelBook As Object
    Dim ExcelSheet As Object
    Dim j As Integer
    Dim myOutputFile As String = "C:\Users\Desktop\Image.jpg"
    PictureBox1.Image.Save(myOutputFile, System.Drawing.Imaging.ImageFormat.Jpeg)

    'create object of excel
    ExcelApp = CreateObject("Excel.Application")
    ExcelBook = ExcelApp.WorkBooks.Add
    ExcelSheet = ExcelBook.WorkSheets(1)

    With ExcelSheet
        For Each column As DataGridViewColumn In DataGridView1.Columns
            .cells(1, column.Index + 1) = column.HeaderText
        Next
        Dim excelRowIndex = 2
        Dim picX = 50
        Dim picY = 50
        For Each row As DataGridViewRow In DataGridView1.Rows
            For j = 0 To DataGridView1.Columns.Count - 1
                If (j = 0) Then
                    .Shapes.AddPicture("C:\Users\Desktop\Image.jpg", Microsoft.Office.Core.MsoTriState.msoFalse,
                                       Microsoft.Office.Core.MsoTriState.msoCTrue, picX, picY, 200, 200)
                    picX += 10
                    picY += 10
                Else
                    .cells(excelRowIndex, j + 1) = row.Cells(j).Value
                End If
            Next
            excelRowIndex += 1
        Next
        Dim formatRange As Excel.Range
        formatRange = ExcelSheet.Range("A1")
        formatRange.EntireRow.Font.Bold = True
        formatRange = ExcelSheet.Range("A1", "A1")
        formatRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue)
        formatRange.BorderAround(Excel.XlLineStyle.xlContinuous)
        formatRange = ExcelSheet.Range("a1", "A1")
        formatRange.EntireRow.BorderAround()
    End With

    ExcelApp.Visible = True
    '
    ExcelSheet = Nothing
    ExcelBook = Nothing
    ExcelApp = Nothing
    Application.Exit()
    End
End Sub

回答!

谢谢JohnG

阅读你分享的那个帖子我使用了代码PictureBox1.Image.Save(SaveFilePath, System.Drawing.Imaging.ImageFormat.Jpeg)

非常开心!感谢您的支持和指导。在这个社区中,像你这样的用户鼓励我学习和分享!