我已经在VB中继承了一个项目,这是我不熟悉的语言。该项目是一个自定义Excel功能区,可从存储过程中导出数据。
问题是当前方法要求将DataTable的所有值都转换为字符串,并以类似的方式导出为CSV。虽然这是导出数据的最简单,最快的方法,但是最终用户必须在填充数据后手动将所有非字符串列转换为正确的格式。我正在尝试一种方法,以便根据数据类型对导出数据的每一列进行格式化。
当前方法/原始代码:
Public Sub PopulateExcel(QueryTable As Data.DataTable, SheetName As String)
Dim wsActive As Excel.Worksheet
wsActive = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets.Add()
Dim wb As Excel.Workbook
wb = Globals.ThisAddIn.Application.ActiveWorkbook
Dim intName As Integer = 1
For Each Cell As DataColumn In QueryTable.Columns
wsActive.Cells(3, intName) = Cell.ColumnName
wsActive.Cells(3, intName).Font.Bold = True
wsActive.Cells(3, intName).Interior.Color = RGB(217, 225, 242)
intName += 1
Next
Dim intRow As Integer = 0
Dim strData As String(,) = New String(QueryTable.Rows.Count - 1, QueryTable.Columns.Count - 1) {}
For Each row As DataRow In QueryTable.Rows
Dim intColumn As Integer = 0
For Each Cell As DataColumn In QueryTable.Columns
strData(intRow, intColumn) = row(Cell).ToString()
intColumn += 1
Next
intRow += 1
Next
wsActive.Range(wsActive.Cells(4, 1), wsActive.Cells(QueryTable.Rows.Count + 1, QueryTable.Columns.Count)).Value = strData
wsActive.Columns.AutoFit()
wsActive.Rows.AutoFit()
我很不高兴地尝试了两种解决方案:
1)在没有字符串转换的情况下在 QueryTable 循环中执行导出。
此方法有效,但对性能有相当大的影响,因为它一次分配一个单元格值。
Dim intRow As Integer = 4
For Each row As DataRow In QueryTable.Rows
Dim intColumn As Integer = 1
For Each Cell As DataColumn In QueryTable.Columns
wsActive.Cells(intRow, intColumn) = row(Cell)
intColumn += 1
Next
intRow += 1
Next
wsActive.Columns.AutoFit()
wsActive.Rows.AutoFit()
2)导出数据后,根据列名更改列格式。我对此没有任何运气。
在下面的示例中,我尝试首先导出数据,并在创建列名称时尝试查找名称中带有“ Qty”的任何列,并将列格式转换为数字格式。
Dim intRow As Integer = 0
Dim strData As String(,) = New String(QueryTable.Rows.Count - 1, QueryTable.Columns.Count - 1) {}
For Each row As DataRow In QueryTable.Rows
Dim intColumn As Integer = 0
For Each Cell As DataColumn In QueryTable.Columns
strData(intRow, intColumn) = row(Cell).ToString()
intColumn += 1
Next
intRow += 1
Next
wsActive.Range(wsActive.Cells(4, 1), wsActive.Cells(QueryTable.Rows.Count + 1, QueryTable.Columns.Count)).Value = strData
wsActive.Columns.AutoFit()
wsActive.Rows.AutoFit()
Dim intName As Integer = 1
For Each Cell As DataColumn In QueryTable.Columns
wsActive.Cells(3, intName) = Cell.ColumnName
If Cell.ColumnName.Contains("Qty") Then
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count, intName)).NumberFormat = "$#,##0.00_);[Red]($#,##0.00)"
End If
wsActive.Cells(3, intName).Font.Bold = True
wsActive.Cells(3, intName).Interior.Color = RGB(217, 225, 242)
intName += 1
Next
我觉得必须有一个更好的方法来解决此问题。任何帮助或建议都很好。
非常感谢。
答案 0 :(得分:0)
我坚持使用选项2。在将列名添加到工作表时,列格式由列名决定。仍然不要以为这是最好的方法,但是它现在可以使用。
Dim intName As Integer = 1
For Each Cell As DataColumn In QueryTable.Columns
wsActive.Cells(3, intName) = Cell.ColumnName
If Cell.ColumnName.Contains("Qty") Then
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).NumberFormat = "General"
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value = wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value
End If
If Cell.ColumnName.Contains("Value") Then
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).NumberFormat = "#,##0.00"
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value = wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value
End If
If Cell.ColumnName.Contains("Rate") Then
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).NumberFormat = "#,##0.0000"
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value = wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value
End If
If Cell.ColumnName.Contains("Percentage") Then
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).NumberFormat = "#,##0.0000"
wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value = wsActive.Range(wsActive.Cells(4, intName), wsActive.Cells(QueryTable.Rows.Count + 1, intName)).Value
End If
wsActive.Cells(3, intName).Font.Bold = True
wsActive.Cells(3, intName).Interior.Color = RGB(217, 225, 242)
intName += 1
Next
wsActive.Columns.AutoFit()
wsActive.Rows.AutoFit()