VFP数据导出全攻略:Excel、PDF、CSV、HTML、JSON,一行代码搞定
数据导出是所有业务系统的标配功能。客户要报表、财务要对账、领导要看图——你总不能让人家直接打开你的DBF文件吧。VFP支持多种导出格式,今天全部讲透,总有一种适合你的场景。
一、导出到CSV:最通用的交换格式
CSV是万能格式,任何系统都能打开,VFP原生支持。
1.1 COPY TO命令(最简单)
USEcustomers
COPY TOcustomers.csv TYPE CSV一行命令,自动生成CSV文件。TYPE CSV会把每个字段用逗号分隔,第一行自动加字段名。
1.2 自定义分隔符
*-- 用分号分隔(欧洲常用)
COPY TOcustomers.csv TYPE DELIMITED WITH ; WITH BLANK
*-- 用TAB分隔(便于粘贴到Excel)
COPY TOcustomers.tsv TYPE DELIMITED WITH TAB
*-- 用双引号包裹字符串
COPY TOcustomers.csv TYPE DELIMITED WITH "1.3 导出前筛选数据
*-- 只导出活跃客户
SELECT * FROM customers WHERE status = "active" ;
AND registration_date >= {^2026-01-01} ;
INTOCURSOR cur_active
COPY TO active_customers_2026.csv TYPE CSV二、导出到Excel:COM自动化
需要格式化的Excel报表(合并单元格、公式、颜色),用COM自动化最灵活。
2.1 最简单的两行代码
*-- VFP数据直接写入Excel
LOCAL oExcel, oWorkbook, oSheet
oExcel = CREATEOBJECT("Excel.Application")
oExcel.Visible = .F.&& 后台运行,不显示窗口
oWorkbook = oExcel.Workbooks.Add()
oSheet = oWorkbook.Sheets(1)
oSheet.Name = "客户清单"
*-- 写入表头
USEcustomers SHARED
=AFIELDS(aFields)
FOR i = 1 TO ALEN(aFields, 1)
oSheet.Cells(1, i).Value = aFields[i, 1]
ENDFOR
*-- 写入数据
SELECT * FROM customers INTO CURSOR cur_cust
nRow = 2
SCAN
FOR i = 1 TO FCOUNT()
oSheet.Cells(nRow, i).Value = EVALUATE(FIELD(i))
ENDFOR
nRow = nRow + 1
ENDSCAN
*-- 保存并关闭
*-- 51 = xlOpenXMLWorkbook (.xlsx)
oWorkbook.SaveAs("customers.xlsx", 51)
oWorkbook.Close(.F.)
oExcel.Quit()
RELEASE oExcel
? "导出完成:customers.xlsx"2.2 格式化Excel(加粗、颜色、列宽自适应)
LOCAL nLastRow
nLastRow = RECCOUNT() + 1
*-- 表头加粗 + 蓝色背景
oSheet.Range("A1").Resize(1, FCOUNT()).Font.Bold = .T.
oSheet.Range("A1").Resize(1, FCOUNT()).Interior.Color = RGB(0, 112, 192)
oSheet.Range("A1").Resize(1, FCOUNT()).Font.Color = RGB(255, 255, 255)
*-- 列宽自适应
oSheet.UsedRange.Columns.AutoFit()
*-- 金额列格式化为货币(根据实际列号调整)
oSheet.Range("D2").Resize(nLastRow - 1, 1).NumberFormat = Chr(165) + "#,##0.00"
*-- 设置打印区域
oSheet.PageSetup.PrintArea = oSheet.UsedRange.Address
oSheet.PageSetup.Orientation = 2 && 2 = xlLandscape 横向2.3 导出多张Sheet
*-- 同一工作簿导出多个Sheet
oWorkbook = oExcel.Workbooks.Add()
*-- Sheet1:客户清单
oSheet1 = oWorkbook.Sheets(1)
oSheet1.Name = "客户"
EXPORT_TO_SHEET(oSheet1, "customers", "客户清单")
*-- Sheet2:订单汇总
oSheet2 = oWorkbook.Sheets(2)
oSheet2.Name = "订单"
oSheet2.Range("A1").Value = "customer_id"
oSheet2.Range("B1").Value = "order_cnt"
oSheet2.Range("C1").Value = "total"
SELECTcustomer_id, COUNT(*) AS order_cnt, SUM(amount) AS total ;
FROM orders GROUP BY customer_id INTO CURSOR cur_orders
*... 写入数据...
*-- Sheet3:月度统计(同上结构)
*...
oWorkbook.SaveAs("business_report.xlsx", 51)
oWorkbook.Close(.F.)
oExcel.Quit()
*-- 通用导出函数
FUNCTION EXPORT_TO_SHEET(oSheet, cCursor, cSheetName)
oSheet.Name = cSheetName
SELECT (cCursor)
=AFIELDS(aFields)
* 写表头
FOR i = 1 TO ALEN(aFields, 1)
oSheet.Cells(1, i).Value = aFields[i, 1]
ENDFOR
* 写数据
nRow = 2
SCAN
FOR i = 1 TO FCOUNT()
oSheet.Cells(nRow, i).Value = EVALUATE(FIELD(i))
ENDFOR
nRow = nRow + 1
ENDSCAN
ENDFUNC⚠️ 注意:宏代换
&无法正确处理含分号的多行 SQL 语句。如需动态执行 SQL,建议改用ndX或直接传 Cursor 名而不是 SQL 文本。
三、导出到HTML:网页展示最方便
HTML文件用浏览器直接打开,无需任何软件,最适合分享。
3.1 一行命令导出HTML表格
USEcustomers
COPY TOcustomers.html TYPE HTML生成的HTML是一个标准的<table>表格,可以直接在浏览器打开,也可以内嵌到网页。
3.2 美化HTML表格
VFP TEXTMERGE 是生成动态 HTML 的利器。关键是理解两个转义规则的组合拳:
\<<→ 输出字面字符
<<<expr>>→ 计算表达式并输出结果
这样 HTML 标签用 \<< 转义,变量用 <<>> 计算,两不耽误。
*-- 生成带样式的HTML报表
FUNCTION ExportToHTML(cCursor, cTitle, cOutFile)
SELECT (cCursor)
* 初始化HTML头尾片段
TEXT TO cHead TEXTMERGE NOSHOW PRETEXT 7
\SLIDERPLACEHOLDER0ENDPLACEHOLDER
\<html>
\<head>
\<meta charset="utf-8">
\<title><<cTitle>>\</title>
\<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #1a73e8; border-bottom: 2px solid #1a73e8; padding-bottom: 8px; }
table { border-collapse: collapse; width: 100%; }
th { background: #1a73e8; color: white; padding: 10px; text-align: left; }
td { padding: 8px; border-bottom: 1px solid #ddd; }
tr:hover { background: #f5f5f5; }
tr:nth-child(even) { background: #fafafa; }
.amount { text-align: right; }
.date { color: #666; }
\</style>
\</head>
\<body>
\<h1><<cTitle>>\</h1>
\<p>导出时间:<<TTOC(DATETIME())>></p>
\<table>
\<tr>
ENDTEXT
TEXT TO cTail TEXTMERGE NOSHOW PRETEXT 7
\</table>
\<p style="color:#888;font-size:12px;">共 <<RECCOUNT()>> 条记录</p>
\</body>
\</html>
ENDTEXT
* 写入表头
LOCAL cHtml, i, cFieldName, cVal
cHtml = cHead
FOR i = 1 TO FCOUNT()
cFieldName = FIELD(i)
cHtml = cHtml + \<th> + cFieldName + \</th> + CHR(13)+CHR(10)
ENDFOR
cHtml = cHtml + \</tr> + CHR(13)+CHR(10)
* 写入数据行
SCAN
cHtml = cHtml + \<tr>
FOR i = 1 TO FCOUNT()
cVal = TRANSFORM(EVALUATE(FIELD(i)))
IF"金额"<code style="background: #f5f5f5; padding: 2px 4px; border-radius: 2px;">FIELD(i) OR"价格"</code>FIELD(i) OR"总额"$FIELD(i)
cHtml = cHtml + \<td class="amount"> + cVal + \</td>
ELSE
cHtml = cHtml + \<td> + cVal + \</td>
ENDIF
ENDFOR
cHtml = cHtml + \</tr> + CHR(13)+CHR(10)
ENDSCAN
cHtml = cHtml + cTail
STRTOFILE(cHtml, cOutFile)
ENDFUNC
*-- 使用
USEcustomers
ExportToHTML("customers", "客户清单", "customers.html")TEXTMERGE 转义规则对照表:
写法 | 输出内容 | 适用场景 |
|---|---|---|
\<< | 字面 | HTML 标签 |
<<expr>> | 表达式的值 | 变量、函数结果 |
\\ | 字面 | Windows 路径等 |
四、导出到PDF:打印存档必备
4.1 Excel转PDF(通过COM)
*-- 先导出Excel,再另存为PDF
*--(需要系统已安装虚拟PDF打印机,如 Microsoft Print to PDF)
oExcel = CREATEOBJECT("Excel.Application")
oWorkbook = oExcel.Workbooks.Add()
*... 写入数据(同2.1节)...
oWorkbook.SaveAs("report_temp.xlsx", 51)
* ExportAsFixedFormat 参数:0=PDF,1=XPS
oWorkbook.ExportAsFixedFormat(0, "report.pdf")
oWorkbook.Close(.F.)
oExcel.Quit()⚠️
ExportAsFixedFormat需要系统安装了虚拟 PDF 打印机(Windows 10+ 自带 Microsoft Print to PDF,Windows 11 带 Microsoft Print to PDF 或 HP Smart)。无打印机时会报错。
4.2 VFP报表直接输出PDF
VFP 标准 ReportListener 没有直接指定输出文件名的内置方法。要输出 PDF,标准做法是通过 Windows 虚拟打印机:
*-- 方式一:静默打印到默认打印机(最通用)
LOCAL oListener
oListener = CREATEOBJECT("ReportListener")
oListener.ListenerType = 0 && 0=输出到打印机
oListener.QuietMode = .T.&& 禁止打印对话框
* 如需指定打印机名,用 CommandClauses
oListener.CommandClauses = ""
REPORTFORM myreport OBJECT oListener TO PRINTER NOCONSOLE
*-- 方式二:Print to PDF(Windows 10+)
* 将 "Microsoft Print to PDF" 设为默认打印机后,
* 用方式一即可得到 PDF 文件原理说明: VFP ReportListener 的 ListenerType = 0 将报表交给 Windows 打印机处理。只要系统有一个虚拟 PDF 打印机(如 Microsoft Print to PDF、Foxit PDF Printer 等),打印输出即为 PDF 文件。通过 QuietMode = .T. 可以静默完成,不弹打印对话框。
如果需要指定输出路径,有两个思路:
临时修改默认打印机(适合一次性导出):
*-- 保存原默认打印机 cOldPrinter = SET("PRINTER", 3) && 获取当前默认打印机 *-- 临时切换到 PDF 打印机 DO WHILE SET("PRINTER", 3) # "Microsoft Print to PDF" SET PRINTER TO NAME "Microsoft Print to PDF" ENDDO *-- 执行报表 LOCAL oListener oListener = CREATEOBJECT("ReportListener") oListener.ListenerType = 0 oListener.QuietMode = .T. REPORTFORM myreport OBJECT oListener TO PRINTER NOCONSOLE *-- 恢复原打印机 IF !EMPTY(cOldPrinter) SET PRINTER TO NAME (cOldPrinter) ENDIF用 GDI+ 将报表页面截图存为 PDF(适合无打印机的服务端场景,需要配合 ReportListener.Render)。
⚠️ 不要用
AddReportObjectProperty("PDF_DEVICE", ...)——这不是 VFP ReportListener 基类的标准方法,标准 VFP 里这个方法不存在,调用会报错"找不到属性或方法"。
五、导出到JSON
JSON在API时代是必备格式:
*-- Cursor转JSON
FUNCTIONCursorToJSON(cCursor, cOutFile)
SELECT (cCursor)
LOCAL cJson, i, cFname, cVal
cJson = "[" + CHR(13)+CHR(10)
SCAN
cJson = cJson + " {" + CHR(13)+CHR(10)
FOR i = 1 TO FCOUNT()
cFname = FIELD(i)
cVal = TRANSFORM(EVALUATE(cFname))
* 处理字符串中的引号
IFVARTYPE(EVALUATE(cFname)) = "C"
cVal = ['"] + STRTRAN(cVal, ['"], ['"]) + ['"]
cJson = cJson + ' "' + cFname + '": "' + cVal + '"'
ELSE
cJson = cJson + ' "' + cFname + '": ' + cVal
ENDIF
IF i < FCOUNT()
cJson = cJson + ","
ENDIF
cJson = cJson + CHR(13)+CHR(10)
ENDFOR
cJson = cJson + " }"
IF !EOF()
cJson = cJson + ","
ENDIF
cJson = cJson + CHR(13)+CHR(10)
ENDSCAN
cJson = cJson + "]" + CHR(13)+CHR(10)
STRTOFILE(cJson, cOutFile)
ENDFUNC
*-- 使用
SELECTcustomer_id, customer_name, registration_date, amount ;
FROMcustomers ORDER BY amount DESC ;
INTOCURSOR cur_top
CursorToJSON("cur_top", "top_customers.json")六、一键导出工具函数
写一个通用导出函数,支持任意格式:
DEFINE CLASS DataExporter AS Custom
FUNCTION Export(cSQL, cOutFile, cFormat)
&cSQL INTO CURSOR cur_exp
DO CASE
CASE cFormat = "CSV"
COPY TO (cOutFile) TYPE CSV
CASE cFormat = "HTML"
THIS.ExportHTML("cur_exp", "数据报表", cOutFile)
CASE cFormat = "JSON"
THIS.ExportJSON("cur_exp", cOutFile)
CASE cFormat = "XLSX"
THIS.ExportExcel("cur_exp", cOutFile)
CASE cFormat = "TXT"
COPY TO (cOutFile) TYPE DELIMITED WITH BLANK
OTHERWISE
? "不支持的格式:" + cFormat
RETURN.F.
ENDCASE
? "导出完成:" + cOutFile
RETURN.T.
ENDFUNC
FUNCTION ExportHTML(cCursor, cTitle, cOutFile)
* 见3.2节实现
ENDFUNC
FUNCTION ExportJSON(cCursor, cOutFile)
* 见第5节实现
ENDFUNC
FUNCTION ExportExcel(cCursor, cOutFile)
* 见2.1节实现
ENDFUNC
ENDDEFINE
*-- 使用示例
oExp = CREATEOBJECT("DataExporter")
oExp.Export("SELECT * FROM customers", "customers.csv", "CSV")
oExp.Export("SELECT * FROM customers", "customers.html", "HTML")
oExp.Export("SELECT * FROM customers", "customers.json", "JSON")
oExp.Export("SELECT * FROM customers", "customers.xlsx", "XLSX")总结
格式 | 适用场景 | 难度 | 依赖 |
|---|---|---|---|
CSV | 数据交换、万能格式 | ⭐ | 无 |
Excel (COM) | 需要格式化报表 | ⭐⭐⭐ | Office |
HTML | 网页展示、邮件附件 | ⭐⭐ | 无 |
正式存档、打印 | ⭐⭐ | Office/虚拟打印 | |
JSON | API对接 | ⭐⭐ | 无 |
记住一个原则:能用CSV解决的不用Excel,能用HTML的不用PDF。除非对方有明确的格式要求,否则越简单的格式越通用、越省事。


被折叠的 条评论
为什么被折叠?



