背景
随手记是金蝶出品的一款记账软件,其实还是不错的,不过我从来没有充过会员,一直也长期用着用了有快三年了,已经有快4000条流水了,每天坚持记账也养成了挺好的习惯。不过近期正好在尝试其他的记账APP,所以发现了竟然还有语音记账和自动记账等功能(自动记账利用的是安卓的无障碍功能识别界面内容来触发),试用了一下还挺好用的。因此我就计划迁移出随手记了,迁移到我试用了还不错的一木记账
App来使用。
但是在迁移的过程中却发现随手记APP的Excel导出是需要会员的,我就导出一下就不用你了竟然收我14块钱一个月的费用,实在太不划算了。
账本的设置-高级功能-备份与同步-导出数据到Excel(CSV)竟然是锁住的,免费版用户导出不了,得充值14块钱一个月才行。
于是到处找解决的方案,最后发现,在设置-高级功能-备份与同步-本地备份与恢复,可以进行免费的导出。导出的文件是kdf后缀的文件,不是常见的文件类型,只有随手记app自己可以导入和解析恢复,那么我们要怎么取到里面的账单内容呢?
一顿好找,最后在吾爱破解找到一个大佬的kdf的解析的文章,其实kdf的本质是一个zip的压缩包里面呢包含了一个sqlite数据库,还有一些其他文件,这个sqlite数据库就是我们需要的账单了。但这个sqlite数据库的文件头是被魔改的,需要改回来才能用。
不过可惜,这位吾爱大佬的文章中给的代码是他自己用的,缺少了非常多的关键信息,因此直接执行是无法执行的,同时我要导入一木记账的代码是并没有的,因此努力修改了一下原始的代码思路,目前已经可以直接使用啦!
将随手记kdf解密并生成可阅读的sqlite数据库
首先我们需要从随手记里面“免费”导出kdf账单文件。
在设置-高级功能-备份与同步-本地备份与恢复中导出即可,然后把该文件传输到电脑的某个上,并修改文件名为record.kdf
方便我们后续的处理。
接下来,运行我们的第一个脚本:
import zipfile
import os
def unzip_kbf(input_files=None):
zf = zipfile.ZipFile(input_files)
zf.extractall(path='./')
def ssj_kbf_sqlite_convert(input_file, output_file):
"""
convert ssj data, after kbf unzip to sqlite,convert it to normal sqlite database file
:param input_file: the mymoney.sqlite file path
:param output_file: the convert mymoney.sqlite file path
:return:
"""
sqlite_header = (0x53, 0x51, 0x4C, 0x69,
0x74, 0x65, 0x20, 0x66,
0x6F, 0x72, 0x6D, 0x61,
0x74, 0x20, 0x33, 0x0)
if os.path.exists(output_file):
os.remove(output_file)
with open(input_file, mode='rb') as f:
with open(output_file, mode='wb') as fw:
data_buffer = f.read()
write_buffer = bytearray(data_buffer)
index = 0
while index < len(sqlite_header):
write_buffer[index] = sqlite_header[index]
index = index + 1
fw.write(write_buffer)
print("convert done")
# 执行kbf文件解密
unzip_kbf("record.kbf")
ssj_kbf_sqlite_convert("mymoney.sqlite", "record_decrypt.sqlite")
此时该文件夹即可生成一个已经解密的record_decrypt.sqlite
文件。
这个文件就是可以直接读取数据的数据了,我们使用一些数据库读取的工具就可以查看里面的内容了,比如navicat等等。其中的t_transaction表就是我们交易的账单了。
当然还有其他的一些表还需要进行联立,我们只需要使用sql的知识把我们需要的字段弄出来即可。
生成导入到一木记账的Excel模板
首先一木记账的模板可以在一木记账APP里面导出来,大概长这样:
于是我也给你提供了我测试好可以导入的获取的代码,使用代码之前你需要安装一下三方的库:
pip install pandas xlwt
接下来是代码:
import sqlite3
import pandas as pd
import xlwt
# 连接到SQLite数据库,如果数据库文件不存在,会自动在当前目录创建一个
# 数据库文件名为example.db
conn = sqlite3.connect('record_decrypt.sqlite')
# 创建一个游标对象,用于执行SQL语句
cursor = conn.cursor()
sql = '''SELECT strftime('%Y-%m-%d %H:%M', a.tradeTime / 1000 + 8 * 3600, 'unixepoch') as 日期,
case
when a.type = 1 then '收入'
when a.type = 0 then '支出'
end as 收支类型,
case
when a.type = 1 then (select case
when (select b.currencyType from t_account b where b.accountPOID = a.sellerAccountPOID) = 'CNY' then a.buyerMoney
else (select round(a.buyerMoney * d.rate, 2) from
(select b.currencyType from t_account b where b.accountPOID = a.sellerAccountPOID) c,
t_exchange d where c.currencyType = d.sell)
end)
when a.type = 0 then (select case
when (select b.currencyType from t_account b where b.accountPOID = a.buyerAccountPOID) = 'CNY' then a.buyerMoney
else (select round(a.buyerMoney * d.rate, 2) from
(select b.currencyType from t_account b where b.accountPOID = a.buyerAccountPOID) c,
t_exchange d where c.currencyType = d.sell)
end)
end as 金额,
case
when a.type = 1 then (select d.name from (select b.parentCategoryPOID from t_category b
where b.categoryPOID = a.buyerCategoryPOID) c, t_category d
where c.parentCategoryPOID = d.categoryPOID)
when a.type = 0 then (select d.name from (select b.parentCategoryPOID from t_category b
where b.categoryPOID = a.sellerCategoryPOID) c, t_category d
where c.parentCategoryPOID = d.categoryPOID)
end as 类别,
case
when a.type = 1 then (select b.name from t_category b where b.categoryPOID = a.buyerCategoryPOID)
when a.type = 0 then (select b.name from t_category b where b.categoryPOID = a.sellerCategoryPOID)
end as 子类,
'日常账本' as 所属账本,
case
when a.type = 1 then (select b.name from t_account b where b.accountPOID = a.sellerAccountPOID)
when a.type = 0 then (select b.name from t_account b where b.accountPOID = a.buyerAccountPOID)
end as 收支账户,
a.memo as 备注,
(select c.name
from t_transaction_projectcategory_map b, t_tag c
where b.transactionPOID = a.transactionPOID
and b.projectCategoryPOID = c.tagPOID
and b.type = 2) as 标签,
'' as 地址
FROM t_transaction a
order by a.tradetime desc;'''
# 运行一个查询语句
select_sql = sql
# 使用游标执行查询
cursor.execute(select_sql)
# 获取所有查询结果
results = cursor.fetchall()
# 打印结果
for row in results:
print(row)
# 将结果转换为DataFrame
columns = [column[0] for column in cursor.description] # 获取列名
df = pd.DataFrame(results, columns=columns)
# 关闭游标和连接
cursor.close()
conn.close()
# 使用xlwt库将DataFrame写入Excel文件
excel_filename = '一木记账导入.xls'
# 创建一个Excel工作簿
wb = xlwt.Workbook()
# 添加一个工作表
ws = wb.add_sheet('Sheet 1')
# 将DataFrame数据写入Excel工作表
for col_num, col_data in enumerate(df.columns):
ws.write(0, col_num, col_data) # 写入列名
for row_num, row_data in enumerate(df.values):
for col_num, col_data in enumerate(row_data):
ws.write(row_num + 1, col_num, col_data) # 写入单元格数据
# 保存Excel文件
wb.save(excel_filename)
print(f'数据已成功写入到 {excel_filename}')
完成后生成的文件效果如下:
接下来就很简单了,使用导出好的这个xls文件,在一木记账中打开或者点导入即可成功导入啦!
希望能对大家有所帮助,谢谢!
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com