我试图将列表视图项目导出到Excel工作表,每件事情都很完美 但是当我试图在后台工作人员中这样做时,我会遇到这个错误:
类型' System.InvalidOperationException'的例外情况发生在System.Windows.Forms.dll中但未在用户代码中处理
附加信息:跨线程操作无效:控制' ListView1'从创建它的线程以外的线程访问。
我知道如何解决这个问题,请帮帮我:)。
这是我的代码:
Private Sub PictureBox2_Click(sender As Object, e As EventArgs) Handles PictureBox2.Click
Try
saveFileDialog1.Filter = "Excel File|*.xlsx"
saveFileDialog1.Title = "Save an Excel File"
Application.EnableVisualStyles()
If saveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
If saveFileDialog1.FileName <> "" Then
PictureBox1.Visible = True
BackgroundWorker1.RunWorkerAsync()
End If
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
saveExcelFile(SaveFileDialog1.FileName)
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
PictureBox1.Visible = False
MessageBox.Show("DONE !!")
End Sub
Public Sub saveExcelFile(ByVal FileName As String)
'Try
Dim xls As New Excel.Application
Dim sheet As Excel.Worksheet
Dim i As Integer
xls.Workbooks.Add()
sheet = xls.ActiveWorkbook.ActiveSheet
Dim row As Integer = 1
Dim col As Integer = 1
For i = 0 To Me.ListView1.Columns.Count - 1
sheet.Cells(1, i + 1) = Me.ListView1.Columns(i).Text
Next
For i = 0 To Me.ListView1.Items.Count - 1
For j = 0 To Me.ListView1.Items(i).SubItems.Count - 1 ' here the ERROR !!
sheet.Cells(i + 2, j + 1) = Me.ListView1.Items(i).SubItems(j).Text
Next
Next
row += 1
col = 1
' for the header
sheet.Rows(1).Font.Name = "Microsoft Sans Serif"
sheet.Rows(1).Font.size = 16
sheet.Rows(1).Font.Bold = True
sheet.Rows(1).HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter
Dim mycol As System.Drawing.Color = System.Drawing.ColorTranslator.FromHtml("#20b2aa")
sheet.Rows(1).Font.color = mycol
' for all the sheet without header
sheet.Range("a2", "z1000").Font.Name = "Arial"
sheet.Range("a2", "z1000").Font.Size = 14
sheet.Range("a2", "z1000").HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter
sheet.Range("A1:X1").EntireColumn.AutoFit()
sheet.Range("A1:X1").EntireRow.AutoFit()
xls.ActiveWorkbook.SaveAs(FileName)
xls.Workbooks.Close()
xls.Quit()
'Catch ex As Exception
' MsgBox(ex.Message)
'End Try
End Sub
hello Enigmativity ......
我做你说的但是我有一个小错误:
类型&#39; System.Runtime.InteropServices.COMException&#39;的例外情况发生在Noor Phone.exe但未在用户代码中处理
其他信息:无法访问该文件。请尝试以下操作之一:
•确保所选文件夹。
•确保包含该文件的文件夹不是只读文件。
•确保文件名不包含以下代码之一:&lt;&gt;? []:|或者*
•确保文件名和路径名不超过128个字符。
这是我编辑后的代码:
Private Class BgwData
Public FileName As String
Public Headers As String()
Public Data As String()()
End Class
Private Sub PictureBox2_Click(sender As Object, e As EventArgs) Handles PictureBox2.Click
'Try
Dim data As New BgwData() With _
{ _
.FileName = SaveFileDialog1.FileName, _
.Headers = _
Me.ListView1.Columns _
.Cast(Of System.Windows.Forms.ColumnHeader)() _
.Select(Function(ch) ch.Name) _
.ToArray(), _
.Data = _
Me.ListView1.Items.Cast(Of ListViewItem)() _
.Select(Function(lvi) lvi.SubItems _
.Cast(Of ListViewItem.ListViewSubItem)() _
.Select(Function(lvsi) lvsi.Text) _
.ToArray()) _
.ToArray() _
}
'BackgroundWorker1.RunWorkerAsync(data)
SaveFileDialog1.Filter = "Excel File|*.xlsx"
SaveFileDialog1.Title = "Save an Excel File"
Application.EnableVisualStyles()
If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
If SaveFileDialog1.FileName <> "" Then
PictureBox1.Visible = True
'BackgroundWorker1.RunWorkerAsync()
BackgroundWorker1.RunWorkerAsync(data)
End If
End If
'Catch ex As Exception
' MsgBox(ex.Message)
'End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'saveExcelFile(SaveFileDialog1.FileName)
saveExcelFile(CType(e.Argument, BgwData))
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
PictureBox1.Visible = False
MessageBox.Show("DONE !!")
End Sub
Private Sub saveExcelFile(ByVal data As BgwData)
'Public Sub saveExcelFile(ByVal FileName As String)
'Try
Dim xls As New Excel.Application
Dim sheet As Excel.Worksheet
Dim i As Integer
xls.Workbooks.Add()
sheet = xls.ActiveWorkbook.ActiveSheet
'Dim row As Integer = 1
'Dim col As Integer = 1
'For i = 0 To Me.ListView1.Columns.Count - 1
' sheet.Cells(1, i + 1) = Me.ListView1.Columns(i).Text
'Next
'For i = 0 To Me.ListView1.Items.Count - 1
' For j = 0 To Me.ListView1.Items(i).SubItems.Count - 1 ' here the ERROR !!
' sheet.Cells(i + 2, j + 1) = Me.ListView1.Items(i).SubItems(j).Text
' Next
'Next
Dim row As Integer = 1
Dim col As Integer = 1
For i = 0 To data.Headers.Length - 1
sheet.Cells(1, i + 1) = data.Headers(i)
Next
For i = 0 To data.Data.Length - 1
For j = 0 To data.Data(i).Length - 1
sheet.Cells(i + 2, j + 1) = data.Data(i)(j)
Next
Next
row += 1
col = 1
' for the header
sheet.Rows(1).Font.Name = "Microsoft Sans Serif"
sheet.Rows(1).Font.size = 16
sheet.Rows(1).Font.Bold = True
sheet.Rows(1).HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter
Dim mycol As System.Drawing.Color = System.Drawing.ColorTranslator.FromHtml("#20b2aa")
sheet.Rows(1).Font.color = mycol
' for all the sheet without header
sheet.Range("a2", "z1000").Font.Name = "Arial"
sheet.Range("a2", "z1000").Font.Size = 14
sheet.Range("a2", "z1000").HorizontalAlignment = Excel.XlVAlign.xlVAlignCenter
sheet.Range("A1:X1").EntireColumn.AutoFit()
sheet.Range("A1:X1").EntireRow.AutoFit()
'xls.ActiveWorkbook.SaveAs(FileName)
xls.ActiveWorkbook.SaveAs(data.FileName)'**HERE THE ERROR**
xls.Workbooks.Close()
xls.Quit()
Marshal.ReleaseComObject(sheet)
Marshal.ReleaseComObject(xls)
'Catch ex As Exception
' MsgBox(ex.Message)
'End Try
End Sub
答案 0 :(得分:0)
您应始终确保在UI线程中访问UI的元素时,否则您可能会遇到您遇到的错误。
避免此问题的最简单方法是分离从UI读取数据的代码和编写Excel文件的代码。
首先定义一个用于保存数据的简单类:
Private Class BgwData
Public FileName As String
Public Headers As String()
Public Data As String()()
End Class
我在表单类中定义了它,因为它不需要在表单外部公开。
现在调用后台工作程序的代码需要更改,以便创建BgwData
的实例,填充ListView
中的数据以及文件名,然后发送到工人作为其论据。
Dim data As New BgwData() With _
{ _
.FileName = saveFileDialog1.FileName, _
.Headers = _
Me.ListView1.Columns _
.Cast(Of System.Windows.Forms.ColumnHeader)() _
.Select(Function(ch) ch.Name) _
.ToArray(), _
.Data = _
Me.ListView1.Items.Cast(Of ListViewItem)() _
.Select(Function(lvi) lvi.SubItems _
.Cast(Of ListViewItem.ListViewSubItem)() _
.Select(Function(lvsi) lvsi.Text) _
.ToArray()) _
.ToArray() _
}
BackgroundWorker1.RunWorkerAsync(data)
此代码在PictureBox2_Click
中运行,因此仍在UI线程上。
BackgroundWorker1_DoWork
方法略有变化,可以像这样调用saveExcelFile
:
saveExcelFile(CType(e.Argument, BgwData))
saveExcelFile
的签名更改为Private Sub saveExcelFile(ByVal data As BgwData)
填充电子表格的代码变为:
Dim row As Integer = 1
Dim col As Integer = 1
For i = 0 To data.Headers.Length - 1
sheet.Cells(1, i + 1) = data.Headers(i)
Next
For i = 0 To data.Data.Length - 1
For j = 0 To data.Data(i).Length - 1
sheet.Cells(i + 2, j + 1) = data.Data(i)(j)
Next
Next
当然,成为SaveAs
方法调用的变化很小:
xls.ActiveWorkbook.SaveAs(data.FileName)
另外,作为附注,请记住,在使用COM对象后也需要释放它们:
Marshal.ReleaseComObject(sheet);
Marshal.ReleaseComObject(xls);
答案 1 :(得分:0)
我找到了所有我需要的答案是在加载表单中添加这行代码
CheckForIllegalCrossThreadCalls = False
感谢您的帮助