Excel 无法使用VBA中的ADODB更新字段

Excel 无法使用VBA中的ADODB更新字段,excel,vba,field,adodb,Excel,Vba,Field,Adodb,我的目标是能够从关闭的工作簿中读取和写入单元格值。我使用ADODB获取所需的信息。 文件是由公司网站生成的,因此在使用实际文件之前,我无法更改内容。该文件为Excel格式。单元格中没有公式,只有值。 我想从工作表中获取日期、字符串和整数,但我遇到了一些限制 我编写示例代码是为了向您展示发生了什么: Dim rsConn As ADODB.Connection Dim rsData As ADODB.Recordset Dim strFileName As String Dim strFieldN

我的目标是能够从关闭的工作簿中读取和写入单元格值。我使用ADODB获取所需的信息。 文件是由公司网站生成的,因此在使用实际文件之前,我无法更改内容。该文件为Excel格式。单元格中没有公式,只有值。 我想从工作表中获取日期、字符串和整数,但我遇到了一些限制

我编写示例代码是为了向您展示发生了什么:

Dim rsConn As ADODB.Connection
Dim rsData As ADODB.Recordset
Dim strFileName As String
Dim strFieldNames As String
Dim intValue As Integer

strFileName = "C:\Tests\Sample.xlsx" ' Fullpath to a workbook
'strFieldNames = "CInt([Proj_Year]) as [Proj_Year]"
'strFieldNames = "[Proj_Year]"
strFieldNames = "*"

Set rsConn = New ADODB.Connection
With rsConn
    .ConnectionString = "Data Source=" & strFileName & "; Extended Properties=""Excel 12.0; HDR=YES; "";"
    .Provider = "Microsoft.ACE.OLEDB.12.0"
    .Open
End With

Set rsData = New ADODB.Recordset
With rsData
    .Source = "SELECT " & strFieldNames & " FROM A2:AE500;" ' Sheetname not required
    .ActiveConnection = rsConn
    '.CursorType = adOpenKeyset     ' Tried this - didn't work
    '.CursorType = adOpenDynamic     ' Tried this - didn't work
    .CursorType = adOpenStatic
    .LockType = adLockOptimistic
    .Open
End With

With rsData
    .MoveFirst
    Do While Not .EOF
        ' Getting the value
        intValue = .Fields(0).Value

        ' Make some crazy modifications of the value
        intValue = intValue + 10

        ' Updating
        .Fields(0).Value = intValue   ' this is place where crash happens

        ' Move to the next record
        .MoveNext
    Loop
End With

rsData.Close
Set rsData = Nothing
rsConn.Close
Set rsConn = Nothing
以下是示例工作簿的屏幕截图:

我尝试了几种方法:

  • strFieldNames=“*”
    我得到工作表中的所有列。但是驱动程序试图猜测字段类型,我不喜欢它,因为它的猜测是错误的。例如,单元格I3应该是字符串,但实际上它是
    adDouble
    。因此,读数可能还可以,但我不能作为字符串写回。 我试过使用IMEX=1,但没用,试过MAXSCANROWS=1,Readonly=0,但也没什么运气。我不想触摸windows注册表来修改猜测行

  • strFieldNames=“[Proj_Year]”
    我只收到一列,但我遇到了与第1列相同的限制

  • strFieldNames=“CInt([Proj_年])作为[Proj_年]”
    我收到我想要的类型的所需列。但当我运行代码时,我收到:

  • 无法更新字段

    在代码中:
    .Fields(0).Value=intValue

    在上面的代码中,我一次读写一条记录。我尝试使用GetRows读取所有数据(30列,3000行),然后将数据数组解析到我自己的类中。读取所有数据后,我修改这些数据,并将其一次一条记录写回工作表


    要使此代码正常工作,我需要做什么?

    我通常只使用
    连接
    对象的
    执行
    方法

    MyBefore数据集(这是位于
    文件路径
    变量处的文件中的数据):

    我的之后的数据集:

    Field1  Field2
       1    b
       2    b
       3    c
       4    d
       5    e
    
    这是对我有用的代码

    Const FilePath As String = "C:\Users\MyComputerName\Desktop\Book1.xlsx"
    Const ConnStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FilePath & _
                              ";Extended Properties='Excel 12.0 Xml;HDR=YES';"
    
    Public Sub testUpdate()
        Dim conn As ADODB.Connection: Set conn = New ADODB.Connection
    
        With conn
            .connectionstring = ConnStr
            .Open
            .Execute "Update [Sheet1$] set Field2='b' where Field1=1"
        End With
    
        If conn.State = adopenstate Then conn.Close: Set conn = Nothing
    End Sub
    

    其他一些观察结果
    • strFileName=“C:\Tests\Sample.xlxs”
      似乎不是有效的文件名。所以这可能会给你带来悲伤
    • 数据集的第一行不包含标题,因此使用工作表名称
      [Sheet1$]
      例如,我认为默认值为
      F1、F2、F3
      ,表示字段名(F1=Field1)。如果您想要两全其美,请使用以下表格和范围来限定范围:
      [Sheet1$A1:B10]
      。请参阅更多详细信息

    我通常只使用
    连接
    对象的
    执行
    方法

    MyBefore数据集(这是位于
    文件路径
    变量处的文件中的数据):

    我的之后的数据集:

    Field1  Field2
       1    b
       2    b
       3    c
       4    d
       5    e
    
    这是对我有用的代码

    Const FilePath As String = "C:\Users\MyComputerName\Desktop\Book1.xlsx"
    Const ConnStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FilePath & _
                              ";Extended Properties='Excel 12.0 Xml;HDR=YES';"
    
    Public Sub testUpdate()
        Dim conn As ADODB.Connection: Set conn = New ADODB.Connection
    
        With conn
            .connectionstring = ConnStr
            .Open
            .Execute "Update [Sheet1$] set Field2='b' where Field1=1"
        End With
    
        If conn.State = adopenstate Then conn.Close: Set conn = Nothing
    End Sub
    

    其他一些观察结果
    • strFileName=“C:\Tests\Sample.xlxs”
      似乎不是有效的文件名。所以这可能会给你带来悲伤
    • 数据集的第一行不包含标题,因此使用工作表名称
      [Sheet1$]
      例如,我认为默认值为
      F1、F2、F3
      ,表示字段名(F1=Field1)。如果您想要两全其美,请使用以下表格和范围来限定范围:
      [Sheet1$A1:B10]
      。请参阅更多详细信息

    从A2:AE500中选择“&strFieldNames&”?它是否应该类似于
    strSQL=“SELECT*from[sheet1$]
    ()?from
    后面的
    应该是工作表名称,而不是范围(在任何给定的工作表上)即使您的文件中只有一个工作表。此外,工作表名称后面应该跟一个
    $
    ,并封装在方括号中。添加工作表名称没有任何区别。我怀疑ACE驱动程序在Excel中使用静态光标更改记录集时有问题。您可能需要尝试
    adOpenKeyset
    .Perso最后,我会使用第二个命令对象发出
    UPDATE
    请求。如果我使用
    adOpenKeyset
    strFieldNames=“CInt([Proj_Year])作为[Proj_Year]“
    程序将像以前一样运行。
    UPDATE
    怎么样?你能给我一些例子吗?你需要一个动态的,adlock
    选择”&strFieldNames&“FROM A2:AE500;
    ?是否应该类似于
    strSQL=“SELECT*FROM[sheet1$]”
    ()?在
    From
    后面应该是工作表名称,而不是范围(在任何给定工作表上),即使您的文件中只有一张工作表。此外,图纸名称后面应跟一个
    $
    ,并封装在方括号中。添加工作表名称没有任何区别。我怀疑ACE驱动程序在Excel中使用静态光标更改记录集时存在问题。您可能需要尝试
    adOpenKeyset
    。就我个人而言,我会使用第二个命令对象来发出
    UPDATE
    请求。如果我使用
    adOpenKeyset
    strFieldNames=“CInt([Proj_Year])作为[Proj_Year]”,
    程序将像以前一样运行。更新怎么样?你能给我举一些例子吗?你需要adOpenDynamic、ADLockOptimistic,然后我想知道更多的例子:
    。执行“更新[Sheet1$]set Field2='b',其中Field1=1”
    。如果我想修改以下单元格:B6=“打开”、C12=123、E9=345、I17=Null等等。如果我有300行要修改怎么办。怎么样?关于观察。我写了一个假文件名,因为这只是一个例子。当我使用第二行作为标题行时,我不知道你为什么要说第一行。sheetname不是必需的,我被问到了上面同样的问题。我的观点是Xlxs不是有效的文件扩展名,如果这是一个问题的话。您正在编写更新记录的SQL语句