编写简单的辅助脚本来在 Google 表格上记账
我的第二份工作入职在即,而这一次则真的是完全跑到了一个陌生的城市了。租房,购置相关用品,还尚未工作钱就花掉一堆。尽管我个人之前一直都没有过记账的习惯,但为了让自己能够搞清楚自己的钱都花在哪里了,于是还是决定整个超级无敌无脑简单的账本出来。
顺带一提,这篇文章仅仅是写下来记录一下整个过程,其实整个文章并没有多高的技术含量。如果你熟悉 Excel vba 或者 Google Spreadsheets 脚本的编写而又期望学习一些新的技巧的话,这篇文章不是你想要的文章。

图在这儿,该文章所指的脚本是给数值变动那一列染色的脚本。顺便上表数值是瞎填的
选型?
首先决定的就是搜索现有的账本工具,而发现一部分账本软件过于复杂,另一部分则是使用他们自己的云服务去存储这些信息。由于感觉自己的需求的确很简单,只需要简单的支出收入计算就可以满足,故最终选择不使用复杂的记账平台和软件。
收入支出计算,差不多就是一个 Excel 就能做到的事情,故开始考虑直接使用 Excel 表格加 vba 来辅助完成工作。但考虑到我平时需要使用手机处理事情,以及曾经被Excel Online的用户体验“感动”过,我决定使用另一家的服务来做这件事,也就是 Google Spreadsheets 。
开发?
不同于以往写小工具的时候的复杂需求和复杂流程,如果选择使用表格软件完成这个记账任务其实只需要在指定的单元格填填东西编写公式就好了。于是填写好列的表头:时间,内容,数值变动,变动后结果和备注。然后就完事儿了。
作为账本,需要自动计算的东西其实就两个,即从初始金额开始每次数值变动后的“变动后结果”,以及当前页账本整个算下来的余额。而这两个需求其实也非常简单,只需要公式即可完成。其中整页余额只需要找个格子写个 SUM(C4:C200) (假设变动的值从在C列,从行4开始,计算到4到200行值的和)把变动的值加一块儿就行了。而计算当前行金额变动后的结果也很简单,只需把上一行的结果和这一行变动的数值相加即可。在我的这个例子中,即当前单元格的值为这个单元格上方的值加上这个单元格左方的值,即公式 =INDIRECT("R[-1]C[0]",false)+INDIRECT("R[0]C[-1]",false) 。Tada!一个无脑账本就这么完成了(你什么都没做啊喂!)。
就这么结束了?
由于如果仅仅如此的话,一切的确太过简陋以至于连一篇博客也水不完, 于是还是决定加一点东西进去,即按照颜色标识收入和支出,而这就需要编写简单的脚本处理了。事实上,相比正常的软件开发,这个需求也显得过于简单,所以我们很容易就能得到这种伪代码:
if (这次花的钱钱 > xxx && 这次花的钱钱 < yyy) {
这个格子.设置背景颜色(某个颜色);
} else if (...) {
//...
}
于是我们要做的事情就是,翻文档,看看如何做到上面的事情。
大致阅读文档发现代码有一股 JavaScript 的味道,于是就决定先按 js 的语法套路来写,如果出了问题再查。通过查阅文档可知,获得当前表的方式就是 SpreadsheetApp.getActiveSheet() ,而得到现有表格的数据范围(即这个表的数据情况)则是 getDataRange() 了。当我们对得到的数据取值,只需要 getValues() 即可得到一个映射表,而取得数据范围内某个格子则只需 getCell(行, 列) ,相应的,取得单元格的值使用 getValue() ,为单元格设置背景使用 setBackground("颜色")。
于是我们就可以通过这些来实现为每一个现有行的收入支出结果那一列标识不同背景颜色的代码了。我们在 工具 > 代码编辑器 编写代码即可,代码也异常简单,如下所示。
function setDebtColor() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
for (var i = 4; i <= 200; i++) { // index start at 1
if (i > data.length) break;
// debt row
var cell = range.getCell(i, 3);
var cellValue = cell.getValue();
if (cellValue - 0 > 0.001) { // incoming
if (cellValue > 61 && cellValue <= 261) cell.setBackground("#a0c238");
else if (cellValue > 261) cell.setBackground("#0074bf");
else cell.setBackground("#c4fdb3");
} else if (cellValue - 0 < -0.001) { // outcoming
if (cellValue < -61 && cellValue >= -261) cell.setBackground("#de9610");
else if (cellValue < -261) cell.setBackground("#c93a40");
else cell.setBackground("#fffacd");
} else {
cell.setBackground(null);
}
}
}
如上我们假设C列的4~200行为需要填色的格子,为支出填红色,收入填绿色(大致..),并根据两个阈值(61和261,别问为啥是这个数)把收入或支出的量的多少分为三段填以不同深浅程度的颜色。填充到最后就完成啦。有意思的是,写这段代码之前我完全不熟悉 Spreadsheet 脚本语言的用法(vba我也不熟悉...),这样竟然没碰到语法错误...
值得一提的是,其一,getCell() 的下标是从 1 开始的,头一次点调试发现内容那一列变色了,当时还觉得挺好看,后来才反应过来不对。另一个是,由于实在懒得去系统的了解这一套脚本语言编写方式之类,故我也没有研究有没有浮点数比较运算的问题,于是对于判断等于0这一点,用了上面写的那种方法。
尾声...
我终于又水了一篇博客,于是对于码农来说,能快速翻阅文档查 API 手册来完成自己想要的任务,应该算是基本素养吧。(写这么一篇博客花的时间是写那一小段脚本的三倍多了吧
更重要的是终于知道我的小钱钱都去哪里了(不对
明天就是新工作入职第一天,水一篇博客,希望一切顺利。
2018年4月1日21点50分
编写简单的辅助脚本来在 Google 表格上记账的更多相关文章
- ROS Learning-010 beginner_Tutorials 编写简单的启动脚本文件(.launch 文件)
ROS Indigo beginner_Tutorials-09 编写简单的启动脚本文件 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14.0 ...
- 编写简单的spring mvc程序,在tomcat上部署
编写简单的spring mvc程序,在tomcat上部署 1 用java 配置spring mvc ,可以省去web.xmlpackage hello;import org.springframewo ...
- 小鸟初学Shell编程(二)编写简单的Shell脚本
Shell脚本 编写Python.PHP脚本通常需要掌握语言的函数,那么Shell脚本则不需要,只需要掌握Linux命令就可以编写Shell脚本,因为Shell脚本就是由多个Linux命令组成,通过将 ...
- (八) .launch文件 ---编写简单的启动脚本文件
下面我们将介绍,如何编写一个启动脚本程序:(.launch文件) 还记得我们在 创建ROS软件包教程 中创建的第一个程序包(beginner_tutorials)吗,现在我们要使用它. 在 begin ...
- 利用 Powershell 编写简单的浏览器脚本
生活中有很多事情是低效益,重复性.比如每天上某些网站,先登录再签到打卡,比如每隔一段时间清理回收站的文件等等.一个成熟的软件工程师应该想到用软件解决他. 对于这些简单的小任务,一般用脚本实现.比如Py ...
- python模块之sys和subprocess以及编写简单的主机扫描脚本
python模块之sys和subprocess以及编写简单的主机扫描脚本 1.sys模块 sys.exit(n) 作用:执行到主程序末尾,解释器自动退出,但是如果需要中途退出程序,可以调用sys.e ...
- 学习 Linux,101: 自定义或编写简单脚本【转】
转自:http://www.ibm.com/developerworks/cn/linux/l-lpic1-105-2/index.html 学习如何使用标准的 shell 语法.循环和控制结构,以及 ...
- case编写的httpd简单启停脚本
case编写的httpd简单启停脚本 #!/bin/bash HTTPD="/etc/init.d/httpd" . /etc/init.d/functions case &quo ...
- 手动编写一个简单的loadrunner脚本
loadrunner除了自动录制脚本外,还可以手动编写脚本,通过右键+inset step添加步骤,还可以手动添加事务,集合点等 下面是一个简单的Action脚本,服务是运行在本机的flask服务: ...
随机推荐
- freemarker.core.ParseException:Unexpected end of file reached
1.错误原因 freemarker.core.ParseException:Unexpected end of file reached 2.错误原因 由于在宏定义中,运用组件时没有关闭标签,导致出错 ...
- Linux中挂载Windows共享出来的目录
Windows中1.新建文件夹,创建共享目录 右键文件夹,共享 2.设置访问方式 Everyone,添加确认 Linux-ubuntu中1.安装cifs#sudo apt-get install ci ...
- angular自定义过滤器操作实例
//模块名字var filters = angular.module("customFilter",[]);//过滤器名字filters.filter("uniqueCa ...
- mac下安装ELK
本文主要为自己所走弯路而做的补充,对小白(比如我)来讲某些博客讲的还是高深了,特地来此补充说明一些东西. 主要步骤参考http://blog.csdn.net/ywheel1989/article/d ...
- Mybatis if test 中int判断非空的坑
Mybatis 中,alarmType 是int类型.如果alarmType 为0的话,条件判断返回结果为false,其它值的话,返回true. <if test="alarmType ...
- C# SerialPort自定义串口DCB
C# SerialPort自定义串口DCBChange DCB fields from SerialPort instance CPS:中文DCB结构详解表 译自Change DCB fields f ...
- 描述下@Component,@Repository,@Service,@Scope,@Autowired,@Inject,@Value标记的作用
1.@Component为通用注解. 2.@Repository为持久层组件注解. 3.@Service为业务层组件注解. 4.@Scope为Bean的作用域注解. 5.@Autowired,@Inj ...
- Luogu P3412 仓鼠找$sugar$ $II$
Luogu P3412 仓鼠找\(sugar\) \(II\) 题目大意: 给定一棵\(n\)个点的树, 仓鼠每次移动都会等概率选择一个与当前点相邻的点,并移动到此点. 现在随机生成一个起点.一个终点 ...
- CSA Round #54 $\ $Voting
CSA Round #54 \(\ \)Voting 题目大意: 原题网址:戳我戳我! 一次歌唱比赛中,一位歌手刚刚结束表演,评委正在打分. 一共有 \(n\) 位评委,他们每人可以打 \(1\) 分 ...
- UVa11426 最大公约数之和(正版)
题面 求\(\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}gcd(i, j)\) n<=4000000,数据组数T<=100 答案保证在64位带符号整数范围内(long ...