【问题标题】:Excel VBA Array not receiving all values from stored procedure recordset - different result than running stored procedure outside of ExcelExcel VBA 数组未从存储过程记录集中接收所有值 - 结果与在 Excel 之外运行存储过程不同
【发布时间】:2016-08-05 20:23:18
【问题描述】:

我一直在尝试解决一个难题。我在 MySql 数据库中有一个存储过程,我通过 Excel VBA 应用程序调用它。 VBA 应用程序将记录集传递到一个数组中,然后我使用一个 For 循环将数组中的每个项目放到一个工作表中。

问题出在:记录集中的两个值在 Excel 中一直显示为空白。奇怪的是,两者都在 Array 的中间,而不是开头或结尾。但是,如果我通过另一个查询程序(例如 HeidiSql)调用存储过程,我会收到所有返回的值。我不知道为什么我没有通过 Excel 接收所有值......或者为什么数组没有接收到所有值,无论如何。

提前感谢您的帮助。

这是我的代码:

Sub StartHereFlexFunderCust()

On Error GoTo ErrorHandler

   Dim Password As String
   Dim SQLStr As String
   'OMIT Dim Cn statement. Cn stands for Database Connection
   Dim Server_Name As String
   Dim User_ID As String
   Dim Database_Name As String
   Dim custID As String
   Dim myArray()
   'OMIT Dim rs statement. rs stands for Database Recordset and is the Recordset of what is returned

   Set RS = CreateObject("ADODB.Recordset")
   Server_Name = Range("O10").Value
   Database_Name = Range("O11").Value ' Name of database
   'id user or username. We need to write code to insert the current user into this variable (Application.Username) if possible. But they may not be consistent across all machines.
   'For example mine is "Ryan Willging" and we would have to shorten it to rwillging but others may be rwillging.
   'This is important because if we do not do this all queries will come from the same person and that is not good for debugging.
   User_ID = Range("O12").Value
   Password = Range("O13").Value
   custID = Range("C4").Value 'Deal Number from Start here that we are passing into the stored procedure

    'This is the storedprocedure call and it passes in the value of the DealId to the Stored Procedure
   SQLStr = "call flexFundByCustomer(" + custID + ")"

   Set cn = CreateObject("ADODB.Connection") 'NEW STATEMENT
   'This statement takes the variables from the checklist and passes them into a connection string
   cn.Open "Driver={MySQL ODBC 5.1 Driver};Server=" & _
           Server_Name & ";Database=" & Database_Name & _
           ";Uid=" & User_ID & ";Pwd=" & Password & ";"
    'This statement queries the database using the SQL string and the connection string.
    'The adOpenStatic variable returns a static copy of a set of records that you can use to find data or generate reports. There are other variables that
    'could be used but I think this one will suffice.
   RS.Open SQLStr, cn, adOpenForwardOnly



Debug.Print msg    'or MsgBox msg

   'Take all of the info from the queries and put them into the spreadsheet
   myArray = RS.getrows()
   Dim Fld_Name As String
   Dim Val_of_Field As String

   Dim starthere As Worksheet

   Fld_Name = UBound(myArray, 1)
   Val_of_Field = UBound(myArray, 2)

   Set starthere = ThisWorkbook.Sheets("Start Here")
   MsgBox "No error yet defined Start Here!"
'This little loop works well to dump the recordset into excel. We can then map the correct fields 'k inputs the headers and R inputs the rows returned in the Recordset
   For K = 0 To Fld_Name ' By using a For loop the data is inputed into excel one row at a time
       starthere.Range("U4").Offset(0, K).Value = RS.fields(K).Name
       For R = 0 To Val_of_Field
          starthere.Range("U4").Offset(R + 1, K).Value = myArray(K, R)
       Next
   Next

   RS.Close
   Set RS = Nothing
   cn.Close
   Set cn = Nothing

ErrorHandler:
MsgBox "There's been an error!"
Exit Sub

End Sub

【问题讨论】:

  • 尝试创建一个MVCE - 这将使您自己的调试变得更容易,也让其他人更容易排除故障。
  • 这听起来像是一个游标问题 - 您是否尝试过使用客户端或静态游标?
  • Range("U5").CopyFromRecordset RS 将消除对数组的需求,然后遍历 rs.Fields 以复制字段名称

标签: arrays vba excel stored-procedures ado


【解决方案1】:

考虑使用Range.CopyFromRecordset 方法来避免使用任何数组。或者,如果内存不允许,请在 Recordset 列中使用 Do While Loop

' COLUMN HEADERS
For i = 1 To RS.Fields.Count
    starthere.("Results").Range("U4").Offset(0, i) = RS.Fields(i - 1).Name
Next i

' DATA ROWS        
' COPYFROMRECORDSET APPROACH
starthere.Range("U5").CopyFromRecordset RS  

' DO WHILE LOOP APPROACH   
starthere.Activate 
starthere.Range("U5").Activate

row = 5
Do While Not RS.EOF
   For i = 0 To RS.Fields.Count - 1
       ActiveCell.Offset(0, i) = RS.Fields(i)
   Next i

   row = row + 1            
   ActiveCell.Offset(row, 21)
   RS.MoveNext
Loop 

至于返回空的值可能是MySQL和Excel数据类型不兼容。例如,您可能将表字段设置为 MySQL 的最大小数 (65, 30),这表示最大位数为 65 和最大 30 个小数点,这无法反映在电子表格上。单元格值的当前精度限制为 15 个小数点。

或者,您可能有一个 VARCHAR(65535),即 65,535 字节限制或无限制的开放式 TEXT 列,也无法在电子表格上显示。当前一个单元格中的字符数限制为 32,767。

尝试将列修改为更小的类型:

ALTER TABLE `tableName` MODIFY COLUMN `largenumberfield` DECIMAL(10,7);

ALTER TABLE `tableName` MODIFY COLUMN `largetextfield` VARCHAR(255);

为什么 HeidiSQL 等其他程序会检索值?这可能是由于它们的内部转换功能将数据值强制转换为特定格式(即删除空格、截断值),然后在 Excel 中充分呈现。

【讨论】:

    猜你喜欢
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 2020-07-19
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多