ODBC到.xlsb文件正在将数字数据转换为字符串

时间:2017-10-23 06:14:51

标签: excel vba excel-vba csv odbc

我有一个.xlsb文件,我通过ODBC连接,这些信息直接存储到一个数据库缓存中,然后我用它来玩。至少有四个列始终保存为文本(通过双击数据透视表的一部分并看到绿色标记告诉我它存储为文本来确认),这使得无法进行总结为平均值等操作。我需要找到一种让它们回到数值的方法。

我在网上发现了一些似乎认为Excel根据单元格格式选择数据类型的其他信息,因此我更新了我的代码,因此整个所需的列格式化为数字(“0.00”),但遗憾的是帮助。

代码首先从一个充满.csv文件的目录中获取信息(强制数字格式化的代码也在这里):

For Each objFile In objFolder.Files
    Set tgtSheet = ThisWorkbook.Sheets.Add
    tgtSheet.Name = objFile.Name

    On Error Resume Next
    With tgtSheet.QueryTables.Add(Connection:="TEXT;" & objFile, Destination:=tgtSheet.Range("A1"))
        .TextFileParseType = xlDelimited
        .TextFileCommaDelimiter = True
        .Refresh
    End With
    On Error GoTo 0

    ' ------ Force data formatting onto columns
    lastRow = FindLastCell(tgtSheet).Row
    For i = 1 To UBound(titleArray)
        currCol = ColumnByTitle(tgtSheet, titleArray(i))
        With tgtSheet
            Set columnRange = .Range(.Cells(1, currCol), Cells(lastRow,     currCol)).EntireColumn
            columnRange.NumberFormat = formatArray(i)
        End With
    Next i
Next objFile

其中columnArray和titleArray是长度为4的字符串数组,分别包含相应的列标题和格式。然后输出到.xlsb:

    With ThisWorkbook
        strPath = .Path
        strFile = .FullName
        strFileTemp = strPath & "\DBtemp" & ".xlsb"
        .Worksheets(arrSheets).Copy
    End With

..最后通过在当前工作簿中仍然打开的工作表中构建SQL命令来设置ODB连接:

For i = LBound(arrSheets) To UBound(arrSheets)
    If arrSheets(i) <> ActiveSheet.Name Then
        If strSQL = "" Then
            strSQL = "SELECT * FROM [" & arrSheets(i) & "$]"
        Else
            strSQL = strSQL & " UNION ALL SELECT * FROM [" & arrSheets(i) & "$]"
        End If
    End If
Next i

' ------ set up connection string
strCon = _
    "ODBC;" & _
    "DSN=Excel Files;" & _
    "DBQ=" & strFileTemp & ";" & _
    "DefaultDir=" & strPath & ";" & _
    "DriverId=790;" & _
    "MaxBufferSize=2048;" & _
    "PageTimeout=5"

Set pc = ThisWorkbook.PivotCaches.Add(SourceType:=xlExternal)

' ------ test pivot table to play around with
With pc
    .Connection = strCon
    .CommandType = xlCmdSql
    .CommandText = strSQL
    Set pt = .CreatePivotTable(TableDestination:=ActiveSheet.Range("A1"))
    pt.Name = "TestPivot"
End With

为了清楚起见,我遗漏了一些事情,但是如果他们需要上下文请告诉我!

另外,我这样做的原因(将csv导入到工作表,将它们重新输出到.xlsb,连接到那个)是因为当我尝试通过ADODB记录集导入时,根本无法使用切片器,在这种情况下,这是必要的。

我也知道像powerpivot这样的工具可以很容易地完成这项工作,但遗憾的是我无法使用它们 - 我的计算机上没有管理员权限,安装过程的过程太耗时/不可能。

任何重大帮助或者代表我指出任何明显的疏忽都会非常感激,我花了一整天的时间来解决这个问题!

Edit1:将文件类型从xlsb更改为xlsx不会执行任何操作。此外,在任何一种情况下,列的格式仍然正确设置为数字(“0.00”)。我相信问题可能出在ODBC部分?它似乎没有太多有用的文档。

编辑2: Excel 2010.

编辑3:来自.csv文件的示例输入:

Image date, Image time, Anatomy, View, kVp, mAs, EI, DAP, Reject reason, Status

42005, 3.33E-02, Chest, P.A., 124, 1.7, 135, 9.83,, confirmed       
42005, 3.40E-02, Chest, Lat., 124, 3.9, 137, 23.84,, confirmed      
42005, 3.82E-02, Chest, Lat., 124, 1.6, 95, 9.09,, confirmed        

1 个答案:

答案 0 :(得分:0)

好的,所以我终于解决了这个问题。我完全取消了导入csv文件并将它们导出为.xlsb的步骤,因为它们没有解决格式错误。我重新访问了另一个工作簿中的代码,该工作簿实际上创建了.csv文件并在那里强制我想要的格式:

func testDoesNotAlertReminderIfAuthorised() {

    // given

    // When
    app.tap()
 ....

然后,在我的分析工作簿中,我简化了导入过程以仅使用微软文本驱动程序,并明确要求更新创建的数据透视表版本(使用其他ODBC的东西,我完成它是默认为禁止使用切片器的早期版本)

' ------------------------------------------------------------------------------------
' Create string arrays to handle looking for correct columns and setting the proper
' formatting in them so it doesn't convert to varchar when imported again later
' ------------------------------------------------------------------------------------
ReDim titleArray(1 To 4)
    titleArray(1) = "kVp"
    titleArray(2) = "mAs"
    titleArray(3) = "EI"
    titleArray(4) = "DAP"

ReDim formatArray(1 To 4)
    formatArray(1) = "0.00"
    formatArray(2) = "0.00"
    formatArray(3) = "0.00"
    formatArray(4) = "0.00"

' ------ Force data formatting onto columns
lastRow = FindLastCell(tgtCSV.Sheets(1)).row
For i = 1 To UBound(titleArray)
    currCol = ColumnByTitle(tgtCSV.Sheets(1), titleArray(i))
    With tgtCSV.Sheets(1)
        Set lastCell = .Range(.Cells(1, currCol), Cells(lastRow, currCol)).EntireColumn
        lastCell.NumberFormat = formatArray(i)
    End With
Next i

代码有点凌乱,因为它使用了录制的宏(yuck),但是它可以使用(而且不是超级慢,是的)。