【问题标题】:Can't get Delphi ADOQuery to update or insert into Excel Worksheet无法让 Delphi ADOQuery 更新或插入 Excel 工作表
【发布时间】:2018-05-16 08:21:38
【问题描述】:

我目前正在开发一个程序,该程序的功能是从 Excel 电子表格中读取数据,用户应该能够在其中编辑库存数量并生成仅使用的库存的单独报告,我已经这样做了。我的问题发生在尝试更新原始电子表格时,显示随着用户在程序上添加/删除库存变得更少/更多。

我已经能够在 DBGrid 中显示库存的变化,但在实际的电子表格上没有进行任何更改,因此每当重新启动程序时,它都会显示不变的数字。(这是使用 DBEdits 完成的)

**我已经创建了此代码的较小版本,希望使我的问题更清晰,更易于阅读。利用查询来尝试更新 Excel 电子表格,电子表格中的第一行的值为 17程序试图更改为 5。每当我运行此代码时,我都会收到“更新语句中的语法错误”,我很确定情况并非如此。我玩过添加诸如

之类的代码

ADOQuery.open ADOQuery.Enabled := 假 ADOQuery.Enabled := true

等等。每个都给我不同的错误。**

代码如下:

procedure TForm1.FormCreate(Sender: TObject);
begin

  //Building Connection string as well as recieving filename of excel document
  OpenDialog1.Execute;
  ADOQuery1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;' + 'Data Source=' + OpenDialog1.FileName + ';' + 'Extended Properties="Excel 8.0;IMEX=2"';

  //Working SQL statement to display records in DBGrid
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM [Sheet1$];');
  ADOQuery1.Active := true;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   //Broken code, purpose is to replace the first row value with a new value
   ADOQuery1.SQL.Clear;

   ADOQuery1.SQL.Add('UPDATE [Sheet1$]');
   ADOQuery1.SQL.Add('SET Value = 5');
   ADOQuery1.SQL.Add('WHERE Value = 17;');

   ADOQuery1.ExecSQL;


end;

end.

示例电子表格: Sample Spreadsheet used in code above

在过去的两天里,我一直在研究这个问题,但不知何故,我似乎一直没有找到答案,询问始终是最后的努力。如果您不知道解决方案,我们将不胜感激任何指导,甚至是对其他编程语言/IDE 的建议,这将给我带来更富有成效的结果。如果您能够将一个可能与我当前程序相关的链接到我,我什至会接受 Excel 脚本教程

P.S 很抱歉这么长的帖子,这个网站还很新。非常感谢所有帮助。

【问题讨论】:

  • 有趣的 q,+1,因为从谷歌结果来看,其他人似乎没有使用 Sql 更新工作表来解决这个问题。我想我知道为什么 - 请参阅我的更新答案。

标签: excel delphi ado tadoquery data-controls


【解决方案1】:

我可以重现你的问题并得到

UPDATE 语句中的语法错误。

更新答案我尚未对此进行全面调查,但我认为您的问题是由于您选择 Value 作为列名而出现的。我认为这个名称可能与 ADO 层解释 UPDATE 语句的方式相冲突。我认为是因为如果我使用这个 Sql 语句

'更新 [Sheet1$] 设置 [Value] = 88 其中 [Value] = 5'

,查询正确执行并正确更新包含5的单元格的值。

我将把我原来的答案留在下面,以防它帮助其他人。

原答案:

为了检查Value 列的字段名称是否有问题,我将其添加到TForm1.Create

  Caption := AdoQuery1.Fields[0].FieldName;

这证实了 FieldName 确实是Value

然后我在表单中添加了一个 TDBNavigator 和 TDBEdit,发现我可以在 TDBEdit 中编辑Value 值而没有任何问题。

这给了我一个想法:

procedure TForm1.Button2Click(Sender: TObject);
begin
  if AdoQuery1.Locate('Value', '5', []) then begin
    AdoQuery1.Edit;
    AdoQuery1.FieldByName('Value').AsString := '99';
    AdoQuery1.Post;
  end;
end;

而且效果很好。显然,这并不完全是您想要的,因为它不能完全复制 UPDATE 语句在有多行匹配 WHERE 子句时会执行的操作,但是您可以通过多种方式实现这一目标,例如使用 AdoQuery 的 Seek 方法。

如果我在 UPDATE 工作方面取得任何进展,我将发布对此答案的更新。

【讨论】:

  • 抱歉,如果在 q.使用 q 中的代码,在 Button1Click 执行后,a) DBGrid 是 empty 因为执行 ExecSQL 会关闭 AdoQuery1 的数据集和 b),值 88(如我的回答)在ExecSQL 执行后立即存储在磁盘上的工作表中。所以,如果你得到不同的结果,那是因为你做的事情与你的 q.但我看到你现在已经删除了我正在回复的评论。
  • 非常感谢您的快速回复!您的原始答案在我的示例代码上完美运行,并且有点烦躁它应该适用于我的主要项目。遗憾的是,您更新的答案目前不适用于我的示例代码,但我会进一步调查。在我的主要项目开始工作之前,我将保持这个线程打开,但我相信我们在这里有一个赢家。
  • 我删除了之前的评论,因为我的措辞不完全是我想要通过的方式,空的 DBGrid 与我无关,据我所知,即使 DBGrid 是空的我仍应在 Excel 电子表格上看到我没有看到的更改。我将在接下来的 2 小时内保留此评论,然后我将删除它以及您的评论,该评论指的是先前删除的内容以进行澄清。
  • 好的,但实际上,你只能删除自己的cmets。
  • 如前所述,我对这个网站还很陌生:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 2019-06-19
  • 1970-01-01
  • 2012-09-07
相关资源
最近更新 更多