【问题标题】:How do I set a MySQL/ODBC connection in Excel from Delphi?如何从 Delphi 在 Excel 中设置 MySQL/ODBC 连接?
【发布时间】:2021-01-02 03:28:56
【问题描述】:

我想从 Delphi 创建一个新的 Excel 工作簿,但在从 Delphi 打开它之前,我首先想建立一个到现有 MySQL 数据库的 ODBC 连接,并设置查询。 然后当它打开时,它会立即提取数据。

我首先尝试在 Excel 中记录宏,然后查看它是如何在 VBA 中建立连接的。 然后我尝试在 Delphi 中复制 VBA。

这是我尝试过的:

var
xls, wb : OLEVariant;
begin
  xls := CreateOLEObject('Excel.Application'); {initialize an instance of Excel}
  wb := xls.Workbooks.Add; {create workbook}

  //xls.ActiveSheet.ListObjects.Add(SourceType:=0, Source:='ODBC;DSN=MySQL;', Destination:=Range('$A$1')).QueryTable; //this throws a missing operator or semicolon error
  xls.Worksheets[1].ListObjects.Add(); //add a listobject
  xls.WorkBooks[1].Worksheets[1].ListObjects.Item[1].QueryTable[1].CommandText := 'SELECT 1';
...
end;

在尝试设置 CommandText 时,我收到 OLE 错误 800A03EC

下面是 VBA 代码。 我通过从新工作簿中记录宏来获得它。 在第一行,我尝试了很多关于如何输入连接字符串的组合,最终我发现我可以添加一个 ListObject(就像在我的 Delphi 代码中一样)而不会出现任何错误,然后我尝试分别设置每个参数,但没有成功。

Sub Macro1()
'
' Macro1 Macro
'

'
    Application.CutCopyMode = False
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:="ODBC;DSN=MySQL;", _
        Destination:=Range("$A$1")).QueryTable
        .CommandType = 0
        .CommandText = Array("SELECT 1")
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .ListObject.DisplayName = "Table_Query_from_MySQL"
        .Refresh BackgroundQuery:=False
    End With
End Sub

【问题讨论】:

  • 告诉 Excel QueryTable1 引用 MySql 数据库中的表的代码是什么以及在哪里?您的 q 需要 minimal, reproducible example。
  • 这是我的问题,我不知道之前需要什么,因此我只是使用“SELECT 1”查询来尝试测试它,因为它不会引用现有表。我昨天和今天都在寻找需要包含的内容,但进展甚微。我找到的都是VB代码。
  • 请显示您说它有效的 VBA 代码。使用该代码编辑您的问题。
  • 查看 ActiveSheet.ListObjects.Add() 的 Delphi 代码。将其与 VBA 代码 ActiveSheet.ListObjects.Add(SourceType:=0, Source:="ODBC;DSN=MySQL;", Destination:=Range("$A$1")).QueryTable 进行比较。你看不出两者的区别吗?
  • @KenWhite:感谢您让我大笑一天。也许 OP 没有意识到他需要使用他的 MySql 数据库的 DSN 名称将工作表链接到 ODBC 数据源。

标签: excel delphi ole listobject


【解决方案1】:

这是一个几乎直接复制 VBA 代码的解决方案:

procedure TForm1.Button1Click(Sender: TObject);
var
    ExcelApplication       : Variant;
    WorkBook               : Variant;
    ActiveSheet            : Variant;
    ListObject             : Variant;
    Range                  : Variant;
    QueryTable             : Variant;
begin
    ExcelApplication                    := CreateOLEObject('Excel.Application');
    WorkBook                            := ExcelApplication.Workbooks.Add;
    ActiveSheet                         := ExcelApplication.ActiveSheet;
    Range                               := ActiveSheet.Range['A1', 'A1'];
    ListObject                          := ActiveSheet.ListObjects.Add(
                                  0,                 // SourceType,
                                  'ODBC;DSN=MySQL;', // Source,
                                  TRUE,              // LinkSource,
                                  xlGuess,           //XlListObjectHasHeaders,
                                  Range);            // Destination
    QueryTable                          := ListObject.QueryTable;
    QueryTable.CommandType              := xlCmdSql;
    QueryTable.CommandText              := 'SELECT 1';
    QueryTable.RowNumbers               := FALSE;
    QueryTable.FillAdjacentFormulas     := FALSE;
    QueryTable.PreserveFormatting       := TRUE;
    QueryTable.RefreshOnFileOpen        := FALSE;
    QueryTable.BackgroundQuery          := TRUE;
    QueryTable.RefreshStyle             := xlInsertDeleteCells;
    QueryTable.SavePassword             := FALSE;
    QueryTable.SaveData                 := TRUE;
    QueryTable.AdjustColumnWidth        := TRUE;
    QueryTable.RefreshPeriod            := 0;
    QueryTable.PreserveColumnInfo       := TRUE;
    QueryTable.ListObject.DisplayName   := 'Table_Query_from_MySQL';
    QueryTable.Refresh(False);  // BackgroundQuery
end;

如您所见,我使用中间变量来提高代码的可读性。你可以省略其中的一些。

【讨论】:

  • 我无法让 xlCmdSql、xlInserrtDeleteCells 和 xlGuess 不抛出错误,所以我将它们删除。
  • ListObject := ActiveSheet.ListObjects.Add( SourceType := 0, Source := 'ODBC;DSN=MySQL;', Destination := Range);
  • @Shamusvw 你说“我无法让 xlCmdSql、xlInserrtDeleteCells 和 xlGuess 不抛出错误,所以我删除了它们。”。有哪些错误?编译时间?运行时间?
  • 这是一个编译时错误,未声明的标识符" 'xlGuess'。对于以 xl 开头的任何其他标识符类似,例如 xlInsertDeleteCells 但我只是删除它们,它给了我想要的东西,即打开创建了 ODBC 连接并通过查询提取数据的 Excel 电子表格。感谢您的帮助,非常感谢您坚持不懈地与我一起工作。
  • xlGuess 等标识符在 Delphi 自带的 Excel2000.pas 中定义。将 Excel2000 添加到您的 uses 子句,或使用这些 const 定义: xlGuess = $00000000; xlCmdSql = $00000002; xlInsertDeleteCells = $00000001;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多