
1. Delphi 读写 Excel 总报错先看清 OLE/COM 到底卡在哪Delphi 读写 Excel 这件事说简单也简单说坑也真不少。核心检索词就三个Delphi、Excel、OLE/COM。你只要用CreateOleObject(Excel.Application)这条路本质上就是在跟 Windows 的 COM 组件打交道而 COM 组件最擅长的就是给你抛一堆看不懂的 HRESULT 错误码。我见过太多 Delphi 老项目导出 Excel 的功能平时跑得好好的换台机器就报「接口未知」「OLE 错误 800A03EC」或者中文列头变成乱码客户一催就头大。先说清楚这套方案能做什么、适合谁。如果你手上是 Delphi 7 到 Delphi 11 的桌面应用需要把数据库里的数据导出成 xlsx或者反过来读 Excel 往数据库里灌那这篇就是给你写的。适合的场景包括ERP 报表导出、进销存对账单生成、批量导入客户资料。不适合的场景是服务器端无人值守的高并发导出——那种情况 OLE 本身就不可靠得换纯文件格式库。为什么 OLE 这么容易出问题因为Excel.Application是一个进程外的 COM 服务器你的 Delphi 程序只是发指令的客户端。Excel 没装、版本不对、权限不够、前一次没释放干净都会让下一次调用直接崩。更麻烦的是很多报错信息是英文的 HRESULT比如0x800A03EC你搜半天也未必对得上。那 TaoToken 在这里扮演什么角色它不是替代 OLE 的而是解决另一条链路的问题当你的 Delphi 程序需要调用大模型来做数据清洗、列头翻译、字段映射或者把导出的数据再走一遍智能处理时你需要一个统一的 Key 和 API 通道。以前你可能每个功能模块各配一套 Key散落在 ini 文件里换一个就全乱。用 TaoToken 统一 Key 之后Delphi 里只需要维护一份配置所有 AI 相关的调用都走同一个入口省心很多。我试过的典型组合是这样的Delphi 负责本地 OLE 读写 Excel保证数据落表TaoToken 负责在导出前后做智能处理比如把中文列头自动转成英文数据库字段名或者校验数据格式。两条链路各司其职互不干扰。下面我会先讲 TaoToken 的前置准备再给可复制的 Delphi 配置片段然后带你走三步验证最后把常见报错一个个拆开。2. TaoToken 前置准备统一 Key 与 API 通道怎么配在动手写 Delphi 代码之前先把 TaoToken 这边的准备工作做完。这一步不复杂但顺序别搞反否则后面调试会浪费很多时间。首先明确一点TaoToken 提供的是统一的 API 通道你拿到一个 Key 之后所有模型调用都通过这个 Key 走。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基础地址是 https://taotoken.net/api 。注意 API 地址后面不要加 UTM 参数直接用它就行。第一步注册并登录后进入控制台。控制台入口在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。进去之后你能看到自己的账户信息和用量统计。第二步创建 API Key。在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 这个页面点新建系统会生成一串以sk-开头的 Key。复制下来存好这个 Key 只显示一次丢了就得重新建。建议你给不同的项目建不同的 Key方便后面按项目排查用量。第三步确认你要用的模型 ID。TaoToken 支持多种模型具体列表可以在文档里查https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。比如你要做文本处理就选对应的对话模型要做代码相关的选 coding 类模型。记下模型 ID后面 Delphi 配置里要填。第四步如果你打算长期做编码或 Agent 类任务可以了解一下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。它适合需要持续调用、用量比较大的场景比按次计费更划算。这里有个关键点要提醒TaoToken 的 API 是标准的 HTTP 接口Delphi 里调用它跟调用任何 REST API 一样用TIdHTTP或者NetHTTPClient都行。它跟 OLE 完全是两码事不要混在一起理解。OLE 是本地进程间通信TaoToken 是网络请求。你的 Delphi 程序可以同时用这两套东西互不影响。配置的时候我建议你把 Base URL、Key、Model ID 这三样东西单独放在一个配置文件里比如config.ini而不是硬编码在源码里。这样换环境的时候只改配置不用重新编译。下面一节我会给出具体的配置片段。还有一点如果你用的是 Claude Code 或者类似的编码工具TaoToken 也提供了对应的接入方式文档里有说明。但 Delphi 这边我们主要还是走原生 HTTP 调用这样最可控。3. 可复制配置Delphi 调用 TaoToken 的完整片段这一节是重点我直接给你能复制粘贴的代码和配置。先说配置文件再说 Delphi 单元。先建一个taotoken.ini放在程序目录下[TaoToken] BaseURLhttps://taotoken.net/api APIKeysk-你的Key粘贴在这里 ModelID你的模型ID Timeout30000然后是 Delphi 的调用单元。我用System.Net.HttpClient来写Delphi 10.3 以上都支持。如果你用的是更老的版本可以换成TIdHTTP逻辑一样。unit uTaoTokenClient; interface uses System.SysUtils, System.Classes, System.Net.HttpClient, System.Net.HttpClientComponent, System.Net.URLClient, System.JSON, System.IniFiles; type TTaoTokenClient class private FBaseURL: string; FAPIKey: string; FModelID: string; FTimeout: Integer; procedure LoadConfig(const AIniFile: string); public constructor Create(const AIniFile: string); function Chat(const APrompt: string): string; end; implementation constructor TTaoTokenClient.Create(const AIniFile: string); begin inherited Create; LoadConfig(AIniFile); end; procedure TTaoTokenClient.LoadConfig(const AIniFile: string); var Ini: TIniFile; begin Ini : TIniFile.Create(AIniFile); try FBaseURL : Ini.ReadString(TaoToken, BaseURL, https://taotoken.net/api); FAPIKey : Ini.ReadString(TaoToken, APIKey, ); FModelID : Ini.ReadString(TaoToken, ModelID, ); FTimeout : Ini.ReadInteger(TaoToken, Timeout, 30000); finally Ini.Free; end; end; function TTaoTokenClient.Chat(const APrompt: string): string; var HTTP: THTTPClient; ReqBody: TStringStream; Resp: IHTTPResponse; JsonReq, JsonResp: TJSONObject; Messages: TJSONArray; MsgObj: TJSONObject; Content: string; begin Result : ; HTTP : THTTPClient.Create; try HTTP.ConnectionTimeout : FTimeout; HTTP.ResponseTimeout : FTimeout; JsonReq : TJSONObject.Create; try JsonReq.AddPair(model, FModelID); Messages : TJSONArray.Create; MsgObj : TJSONObject.Create; MsgObj.AddPair(role, user); MsgObj.AddPair(content, APrompt); Messages.AddElement(MsgObj); JsonReq.AddPair(messages, Messages); ReqBody : TStringStream.Create(JsonReq.ToJSON, TEncoding.UTF8); try HTTP.CustomHeaders[Authorization] : Bearer FAPIKey; HTTP.CustomHeaders[Content-Type] : application/json; Resp : HTTP.Post(FBaseURL /v1/chat/completions, ReqBody); if Resp.StatusCode 200 then begin JsonResp : TJSONObject.ParseJSONValue(Resp.ContentAsString(TEncoding.UTF8)) as TJSONObject; try Content : JsonResp.GetValuestring(choices[0].message.content); Result : Content; finally JsonResp.Free; end; end else raise Exception.CreateFmt(HTTP %d: %s, [Resp.StatusCode, Resp.ContentAsString]); finally ReqBody.Free; end; finally JsonReq.Free; end; finally HTTP.Free; end; end; end.这段代码的关键点Base URL 用的是https://taotoken.net/api请求路径拼上/v1/chat/completions认证头是Bearer加你的 Key。Model ID 从配置读不写死。接下来是 Excel 导出部分。这里我用 OLE 写 xlsx同时把中文列头处理好。注意编码问题Delphi 的字符串默认是 UnicodeString写进 Excel 一般不会乱码但如果你的数据来自 ANSI 编码的旧数据库就要先转码。procedure ExportToExcel(const AFileName: string; ADataSet: TDataSet); var XLApp, Workbook, Sheet: Variant; Col, Row: Integer; FieldName: string; begin XLApp : CreateOleObject(Excel.Application); try XLApp.DisplayAlerts : False; XLApp.ScreenUpdating : False; Workbook : XLApp.WorkBooks.Add; Sheet : Workbook.Worksheets[1]; // 写中文列头 for Col : 0 to ADataSet.FieldCount - 1 do begin FieldName : ADataSet.Fields[Col].DisplayName; Sheet.Cells[1, Col 1] : FieldName; end; // 写数据 ADataSet.First; Row : 2; while not ADataSet.Eof do begin for Col : 0 to ADataSet.FieldCount - 1 do Sheet.Cells[Row, Col 1] : ADataSet.Fields[Col].AsString; Inc(Row); ADataSet.Next; end; Workbook.SaveAs(AFileName, 51); // 51 xlOpenXMLWorkbook, 即 xlsx finally if not VarIsEmpty(XLApp) then begin XLApp.DisplayAlerts : False; XLApp.ScreenUpdating : True; XLApp.Quit; XLApp : Unassigned; end; end; end;注意SaveAs的第二个参数51这是 xlsx 格式的常量。如果你用xlNormal或者不传可能存成老格式中文兼容性反而更差。另外XLApp.Quit之后一定要Unassigned否则 Excel 进程会残留在任务管理器里下次调用就可能报「服务器执行失败」。4. 三步验证本地生成 xlsx、校验中文列头、确认接口状态码配置写完了别急着上生产先按这三步验证一遍。每一步都有明确的成功标准走完你就知道链路通没通。第一步本地生成 xlsx。写一个最简单的测试程序造一个TClientDataSet或者直接用TADOQuery查几条数据调用上面的ExportToExcel存到C:\temp\test.xlsx。运行之后去文件夹看文件存在且大小不为 0就说明 OLE 这条链路是通的。如果报错先看是不是 Excel 没装或者当前用户没有权限创建 COM 对象。这一步不涉及 TaoToken纯粹验证本地 Excel 读写。第二步校验中文列头。用 Excel 打开刚才生成的文件看第一行的列头是不是正常显示中文。如果显示成问号或者方块说明编码有问题。常见原因是你的数据源字段名本身是 ANSI 编码赋值给 Variant 的时候没有正确转换。解决办法是在赋值前用UTF8Decode或者TEncoding.Convert转一遍。另外如果你用的是 Delphi 7 这种老版本默认字符串是 ANSI那就要特别注意建议升级到 Unicode 版本或者手动处理编码。第三步确认接口返回状态码。写一个小测试调用TTaoTokenClient.Chat(你好)看返回内容是否正常。成功的话你会拿到一段文本回复。如果返回 401说明 Key 不对或者没带上如果返回 404检查 Base URL 和路径拼接如果超时检查网络和 Timeout 设置。这一步验证的是 TaoToken 通道跟 Excel 无关但它是你后续做智能处理的基础。三步都通过之后你可以把两步串起来先调 TaoToken 把列头翻译成英文再写进 Excel或者先导出 Excel再调 TaoToken 做数据校验。串行调用的时候注意异常处理任何一步失败都要能回滚别让 Excel 进程卡住。这里给一个串行调用的示例片段var Client: TTaoTokenClient; TranslatedHeader: string; begin Client : TTaoTokenClient.Create(taotoken.ini); try TranslatedHeader : Client.Chat(把“客户名称”翻译成英文数据库字段名只返回字段名); // 把 TranslatedHeader 写进 Excel 第一行 finally Client.Free; end; end;实测下来这套组合的稳定性主要取决于两个点Excel 进程有没有正确释放以及 TaoToken 的 Key 有没有过期。前者靠try...finally保证后者靠定期检查控制台用量。5. 常见报错排查401、local proxy failed、reading choices、OAuth这一节我把实际踩过的坑列出来对照着排查能省不少时间。401 Unauthorized。这个最直接就是 Key 有问题。检查三件事Key 是不是复制完整了有没有多余空格请求头是不是Bearer加 Key注意 Bearer 后面有个空格Key 是不是被删了或者过期了。去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 重新生成一个再试。如果还是 401检查你的 Base URL 是不是写成了https://taotoken.net/api/带了多余的斜杠拼接后路径变成//v1/...有些服务端会拒绝。local proxy failed。这个报错通常出现在你本地配了代理但代理没启动或者配置不对。Delphi 的THTTPClient默认会读系统代理设置。如果你不需要代理在代码里显式设置HTTP.ProxySettings : TProxySettings.Create(nil)或者把TProxySettings的Enabled设为 False。注意这里说的是本地网络配置问题跟任何特定工具无关纯粹是 HTTP 客户端的行为。reading choices 相关报错。这个一般是你解析返回 JSON 的时候路径写错了。TaoToken 返回的结构是标准的choices数组第一个元素的message.content才是文本。如果你用GetValuestring(choices[0].message.content)报错先打印完整的返回内容看看结构对不对。有时候服务端返回的是错误信息根本没有choices字段这时候你去读就会报错。正确的做法是先判断StatusCode再判断有没有choices。OAuth 相关报错。如果你在配置里看到了 OAuth 字样说明你可能在用某种需要授权流程的接入方式。对于 Delphi 这种桌面程序最简单的还是用 API Key 直接认证不要走 OAuth 那套。检查你的配置文件确保只用了APIKey没有混入其他认证字段。如果你用的是 Claude Code 或者 Codex 这类工具它们的auth.json或者settings.json里可能有 OAuth 配置但那是工具自己的事跟 Delphi 调用无关。再补充一个 Excel 侧的常见报错OLE error 800A03EC。这个通常是单元格操作越界比如你写Sheet.Cells[0, 0]Excel 的索引是从 1 开始的。或者你打开的文件路径不存在。检查行列索引和文件路径。还有一个Excel 进程残留。表现是任务管理器里有一堆EXCEL.EXE然后新调用越来越慢最后失败。解决办法就是前面说的Quit之后Unassigned并且把DisplayAlerts设回 True 之前先 Quit。顺序别搞反。排查的时候我建议你打开 TaoToken 控制台看请求日志能直接看到每次调用的状态码和耗时。对照日志排查比盲猜快得多。6. 把两条链路串起来Delphi 本地落表 TaoToken 智能处理走到这里你应该已经能跑通本地 Excel 导出也能调通 TaoToken 接口了。最后说说怎么把这两条链路串成一个完整的数据导出流程。典型的流程是这样的Delphi 程序从数据库查出数据先调 TaoToken 做一轮字段映射和格式校验比如把中文列头转成标准英文名把日期格式统一成yyyy-MM-dd把金额字段的小数位补齐。处理完之后再用 OLE 写进 xlsx最后保存到指定目录。整个过程里TaoToken 负责「想」OLE 负责「写」分工明确。如果你要做的是反向操作从 Excel 读数据导入数据库流程反过来先用 OLE 读 xlsx 到内存调 TaoToken 做数据清洗和去重判断再写回数据库。这种场景下TaoToken 的价值在于处理那些规则不固定的脏数据比写一堆 if-else 灵活得多。对于长期跑批的任务建议用 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。它适合需要持续调用、用量稳定的场景。如果你只是偶尔用一下按量付费就够了。验证模型效果的时候可以先用模型对话页面快速试一下https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 。把你要处理的文本贴进去看看返回结果符不符合预期再决定要不要写进 Delphi 代码。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有完整的接口说明和参数列表。遇到不确定的参数先查文档再动手。最后给一个实用技巧在 Delphi 里把 TaoToken 的调用封装成一个独立的线程不要在主线程里同步调用。因为网络请求有延迟同步调用会卡住界面。用TThread或者TTask包一层回调里再更新 UI。这样用户体验好很多也不容易因为超时导致程序假死。Excel 这边如果你要导出的数据量很大比如几万行逐单元格赋值会很慢。可以先把数据拼成一个二维数组再一次性赋值给Range速度能快几十倍。具体做法是构造一个Variant数组然后Sheet.Range[Sheet.Cells[1,1], Sheet.Cells[RowCount, ColCount]].Value : DataArray。这个技巧在处理大批量导出时特别有用。整套方案跑下来你会发现 Delphi 读写 Excel 的报错其实就那么几类摸清楚规律之后排查很快。TaoToken 这边只要 Key 和 Base URL 配对基本不会出问题。两条链路各自稳定串起来就是一套可靠的数据导出方案。