有用户问:App 里记了一堆数据(记账、打卡、测量值),想导出成一个 CSV 文件,再通过微信、QQ 或邮件发给别人,用电脑上的表格软件打开,怎么做?
能实现,不需要拓展。 用到三样现成的东西:
- 列表抽屉的「列表转换为CSV表」:把「列表的列表」(每一项是一行)变成 CSV 文本,逗号、引号、换行这些特殊字符会自动加引号处理;
- 文件管理器的保存文件:把文本写成文件;
- 信息分享器的分享文件:弹出系统分享面板,用户自己选发到哪里。
思路:列表 → CSV 文本 → 存成文件 → 存好了再分享。最后这一步的「存好了再」是关键,下面实验三会讲为什么。
CSV 就是「逗号分隔的纯文本」,一行一条记录,同一行里的各项用逗号隔开。例如:
日期,项目,金额
2026-09-30,午饭,25
2026-09-30,地铁,4
WPS、Excel、Numbers、谷歌表格都能直接打开,一格一格排好。
准备
- 拖两个文本输入框:
文本输入框_项目(提示「项目」)、文本输入框_金额(提示「金额」,勾选「仅限数字」)。 - 拖三个按钮:
按钮_记一笔、按钮_导出、按钮_导入,再拖一个标签标签1显示状态。 - 拖四个非可视组件:微数据库、文件管理器、信息分享器(在「社交应用」里)、计时器。文件管理器和计时器的属性都不用改。
实验一:先把数据记下来
每记一笔就是一行:日期、项目、金额三项组成一个小列表,所有行放进一个大列表 账目,同时存进微数据库,退出 App 再进来数据还在。
global 账目 = []
when Screen1.Initialize() {
账目 = 微数据库1.GetValue("账目", [])
标签1.Text = join("已有 ", length(账目), " 笔")
}
when 按钮_记一笔.Click() {
var 日期 = 计时器1.FormatDateTime(计时器1.Now(), "yyyy-MM-dd")
listAdd(账目, [日期, 文本输入框_项目.Text, 文本输入框_金额.Text])
微数据库1.StoreValue("账目", 账目)
文本输入框_项目.Text = ""
文本输入框_金额.Text = ""
标签1.Text = join("已有 ", length(账目), " 笔")
}
跑起来看: 记三笔,标签依次变成「已有 1 笔」「已有 2 笔」「已有 3 笔」。在伴侣里点「重置连接」重新连上,标签仍然显示 3 笔,说明存住了。
实验二:导出成 CSV 文件
先拼出表头行,再把全部账目接在后面,交给「列表转换为CSV表」变成文本,最后保存:
global 账目 = []
when 按钮_导出.Click() {
if (length(账目) == 0) {
标签1.Text = "还没有数据可导出"
} else {
var 表格 = [["日期", "项目", "金额"]]
listAppend(表格, 账目)
文件管理器1.SaveFile(listToCsvTable(表格), "记账.csv")
}
}
when 文件管理器1.AfterFileSaved(文件名) {
标签1.Text = join("已保存:", 文件名)
}
跑起来看: 点「导出」,标签显示「已保存:记账.csv」。
几点说明:
- 文件名只写名字,不要以
/开头。这样文件落在应用自己的目录里(安卓是Android/data/包名/files/,鸿蒙是应用沙箱),不需要任何存储权限。 - 用
listAppend把账目接到表格后面,而不是直接往账目里插表头:账目是要长期保存的数据,不能被导出动作改掉。 - 项目名里有逗号(比如「午饭,加蛋」)也没关系,「列表转换为CSV表」会自动给这一格加上引号,表格软件打开还是一格。自己用
join拼逗号就会错位,这是推荐用内建积木的原因。
实验三:保存好之后再分享
把实验二的「文件存储完毕时」事件改成直接分享:
when 文件管理器1.AfterFileSaved(文件名) {
标签1.Text = "正在打开分享面板…"
信息分享器1.ShareFile(文件名)
}
跑起来看: 点「导出」,系统分享面板弹出来,选微信发给文件传输助手,电脑上打开就是一张三列的表格。
为什么不在按钮里 SaveFile 下一行直接 ShareFile?因为保存文件是异步的:SaveFile 只是把写文件的活交出去就立刻返回,这时文件可能还没写完,分享出去的是空文件或旧文件。「文件存储完毕时」事件触发时文件一定已经写好了,在这里分享最稳。
为什么只写 文件名 就能找到文件?文件管理器和信息分享器对「不以 / 开头的文件名」用的是同一个默认目录(屏幕的「默认文件范围」,默认值「应用」),两边说的是同一个文件。
实验四:文件名带上日期,附一句说明
每次导出都叫「记账.csv」,对方收到好几份分不清。文件名带上导出时间,分享时再附一句话:
global 账目 = []
when 按钮_导出.Click() {
if (length(账目) == 0) {
标签1.Text = "还没有数据可导出"
} else {
var 表格 = [["日期", "项目", "金额"]]
listAppend(表格, 账目)
var 名字 = join("记账_", 计时器1.FormatDateTime(计时器1.Now(), "yyyyMMdd_HHmm"), ".csv")
文件管理器1.SaveFile(listToCsvTable(表格), 名字)
}
}
when 文件管理器1.AfterFileSaved(文件名) {
信息分享器1.ShareFileWithMessage(文件名, join("共 ", length(账目), " 笔账目,用 WPS 或 Excel 打开"))
}
跑起来看: 分享出去的文件名类似「记账_20260930_1830.csv」。发到微信时附言会作为单独一条消息,发邮件时会出现在正文里(具体取决于接收的 App)。
实验五:把 CSV 读回列表
导出只是一半,换了手机想把数据导回来也常用。用「读取文件」读出文本,「CSV表转换为列表」变回列表的列表,去掉第 1 行表头就是原来的账目:
global 账目 = []
when 按钮_导入.Click() {
文件管理器1.ReadFrom("记账.csv")
}
when 文件管理器1.GotText(文本) {
var 表格 = listFromCsvTable(文本)
listRemove(表格, 1)
账目 = 表格
微数据库1.StoreValue("账目", 账目)
标签1.Text = join("已导入 ", length(账目), " 笔")
}
跑起来看: 先用实验二的写法导出「记账.csv」,再清空数据(或换一台手机把文件拷进应用目录),点「导入」,标签显示导入的笔数,和导出前一致。
常见问题
| 现象 | 原因 | 解决 |
|---|---|---|
| Excel 打开中文是乱码 | 文件是不带 BOM 的 UTF-8,老版本 Excel 双击打开时按本地编码猜 | 用 WPS、Numbers、新版 Excel 直接打开都正常;老版 Excel 用「数据 → 从文本/CSV」导入,编码选 UTF-8 |
| 分享出去的是空文件或旧内容 | 在 SaveFile 下一行直接分享,文件还没写完 |
放到「文件存储完毕时」事件里分享(实验三) |
| 分享时提示找不到文件 | 保存时文件名以 / 开头,或者改过屏幕的「默认文件范围」、文件管理器的「范围」,两边目录不一致 |
文件名只写名字,两个范围都保持默认「应用」;或者直接把「文件存储完毕时」给的 文件名 原样传给分享 |
| 表格列错位 | 自己用 join 拼逗号,内容里本身带逗号或换行 |
用「列表转换为CSV表」,它会自动加引号 |
| 金额在表格里不能求和 | 输入框里带了空格或「元」字 | 输入框勾选「仅限数字」,或存之前用 trim 去掉空格 |
| 想每次追加而不是覆盖 | SaveFile 会覆盖同名文件 |
用 AppendToFile 追加一行,写入内容用「列表转换为CSV行」再接一个换行;注意第一次要先写表头 |
| 分享面板里没有想要的 App | 接收方 App 没有声明能收这种文件 | 换一个目标(微信、QQ、邮箱、网盘都能收 .csv),或把扩展名改成 .txt 试试 |
平台说明
- 安卓:文件在
Android/data/包名/files/下,不需要存储权限;卸载 App 时会一起删除,要长期保存记得分享或导出出去。 - 鸿蒙:文件管理器的「应用」范围就是应用沙箱,信息分享器按同一个目录解析文件名,本文所有积木原样可用。
相关文档
- 文件管理器
- 信息分享器
- 微数据库
- 使用 JSON 和 Web API:数据要上传到服务器而不是发文件时看这篇
扫码添加客服咨询