Obsidianで収支の計算をする記録

概要

Obsidianで収支の記録をしたい
多分デイリーノートに書いていく感じ
それでプラスとかマイナスを記録していって、0_HomePage - EntryPointかなんかにまとめて表示する。

きっかけ

ちょっとお金の管理をしておきたい
103万の壁とか学費とかの計算をして可視化したかったから

ログ

先駆者がいるはずだからそれを見て自分なりにアレンジして収支報告書を作成してみる。
これをウィークリーレポートとかマンスリーレポートとかに書いて一か月の収支とかしてもいいかもしれない

あとバイトの給料日は決まっているからTemplaterでその日になったら給料を追加してくださいみたいなこともできるかもしれないね

このnoteに結構いろいろ書いてあるから参考にしていこう

どうやらこの記事ではタグで管理してるっぽい
`#仕訳/2024/09/09
タグでやるとdataviewで集計するのが簡単になるポイね

‘‘‘dataview
list from #仕訳/2022/02 sort 日付
‘‘‘

こんな感じ

あんまりやるとタグが煩雑になる気もするけど

この日付と金額とtypeの三つの情報を表すにはちょっと工夫が必要だなー

これでできるならあんまり苦労しなずでできるかも?
まずデイリーノートに
#仕訳/2024/09/09っていうタグをつけよう

デイリーノートにこんな感じの支出をつけた

Transclude of 2024-09-09#支出

これを何とかしてdataviewjsで抜き出したい
こんな感じ

Transclude of Obsidianで支出収入を考える図

ちょっとdataviewjsの勉強しないと

dataviewJS勉強ログ-収支計算から結構勉強してこんな感じになった

```dataviewjs
const column = ["日付", ,"内訳", "収入", "支出", "残金"];

let table = [];

let filesWithTag = dv.pages('#仕訳');
let files = Array.from(filesWithTag);

let zankin = 0;

for(let file of files){
	getShunyu(file);
	getSishutu(file);
}

function addListItem(fileName, utiwake, shunyu, sishutu, zankin){
	let item = [fileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}

function getShunyu(file){
	if(file.収入.constructor === String){
		let item = file.収入.split(":");
		addListItem(file.file.name, item[0], item[1], 0, zankin);
		return;
	}

	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		
		addListItem(file.file.name, item[0], item[1], 0, zankin);
	}
}

function getSishutu(file){
	if(file.支出.constructor === String){
		let item = file.支出.split(":");
		addListItem(file.file.name, item[0], item[1], 0, zankin);
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		
		addListItem(file.file.name, item[0], 0, item[1], zankin);
	}
}

function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}

dv.table(column, table)
```

これは現状、ただデイリーノートから支出と収入のmetatagから値を取得してテーブルにしてるだけ
あと残金計算とか合計とか期間指定とかできたら結構いい感じになるんじゃない?

const column = ["日付", ,"内訳", "収入", "支出", "残金"];
 
let table = [];
 
let filesWithTag = dv.pages('#仕訳');
let files = Array.from(filesWithTag);
 
let zankin = 0;
 
for(let file of files){
	getShunyu(file);
	getSishutu(file);
}
 
function addListItem(fileName, utiwake, shunyu, sishutu, zankin){
	let item = [fileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}
 
function getShunyu(file){
	if(typeof file.収入 === "undefined"){
		return;
	}
	else if(typeof file.収入 === 'string'){
		let item = file.収入.split(":");
		calcZankin("shunyu", item[1]);
		addListItem(file.file.name, item[0], item[1], 0, zankin);
		return;
	}
 
	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		calcZankin("shunyu", item[1]);
		
		addListItem(file.file.name, item[0], item[1], 0, zankin);
	}
}
 
function getSishutu(file){
	if(typeof file.支出 === "undefined"){
		return;
	}
	else if(file.支出.constructor === String){
		let item = file.支出.split(":");
		calcZankin("sishutu", item[1]);
		addListItem(file.file.name, item[0], 0, item[1], zankin);
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		calcZankin("sishutu", item[1]);
		
		addListItem(file.file.name, item[0], 0, item[1], zankin);
	}
}
 
function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}
 
function calcZankin(mode, value){
	if(mode == "shunyu"){
		zankin += parseInt(value);
	}
	else{
		zankin -= parseInt(value);
	}
}
 
dv.table(column, table)

とりあえずこんな感じになった

次は残金の計算をしようかな

```dataviewjs
function calcZankin(mode, value){
	if(mode == "shunyu"){
		zankin += parseInt(value);
	}
	else{
		zankin -= parseInt(value);
	}
}
```

残金計算もできた

これ結構いい感じになってきた
最後に全部の合計も出したほうがいいのかな

それ作ってみるか

const column = ["日付", "内訳", "収入", "支出", "残金"];
 
let table = [];
 
let filesWithTag = dv.pages('#仕訳');
let files = Array.from(filesWithTag);
 
let zankin = 0;
let shunyuResult = 0;
let sishutuResult = 0;
 
createTable();
 
function createTable(){
	for(let file of files){
		getShunyu(file);
		getSishutu(file);
	}
	
	addListItem("合計", "", shunyuResult, sishutuResult, zankin);
	
	dv.table(column, table);
}
 
function getShunyu(file){
	if(typeof file.収入 === "undefined"){
		return;
	}
	else if(file.収入.constructor === String){
		let item = file.収入.split(":");
		calcZankin("shunyu", item[1]);
		addListItem(file.file.name, item[0], item[1], 0, zankin);
		return;
	}
 
	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		calcZankin("shunyu", item[1]);
		
		addListItem(file.file.name, item[0], item[1], 0, zankin);
	}
}
 
function getSishutu(file){
	if(typeof file.支出 === "undefined"){
		return;
	}
	else if(file.支出.constructor === String){
		let item = file.支出.split(":");
		calcZankin("sishutu", item[1]);
		addListItem(file.file.name, item[0], 0, item[1], zankin);
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		calcZankin("sishutu", item[1]);
		
		addListItem(file.file.name, item[0], 0, item[1], zankin);
	}
}
 
function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}
 
function calcZankin(mode, value){
	let intValue = parseInt(value);
	if(mode == "shunyu"){
		zankin += intValue;
		shunyuResult += intValue;
	}
	else{
		zankin -= intValue;
		sishutuResult += intValue;
	}
}
 
function addListItem(fileName, utiwake, shunyu, sishutu, zankin){
	let linkedFileName = "[[" + fileName + "]]";
	let item = [linkedFileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}

デイリーノートに仕訳のタグが自動的に付与されるようにしてみた
今のところは問題はなし!

次は期間指定作ってみようかな
まずinput要素で指定するのはあり?

let value = "";
 
const p = dv.el("input");
p.placeholder = "期間指定のinput要素";
p.style = "width:80%; font-size:18px; background:transparent; margin:32px";
 
const b = dv.el("div", "");
 
p.onkeyup = function () {
	disp();
};
 
function disp(){
	b.innerHTML = "入力された値:" + p.value;
}

これを三つつなげて
年度と月と日を指定できるようにしようかな
でもいちいち入力するのはだるいから
入力された分だけtableに表示できるようにしようかな
ただちょっと再レンダリングするのにひと手間いるのが大変だわ

```dataviewjs
let value = "";

const p = dv.el("input");
p.placeholder = "期間指定のinput要素";
p.style = "width:80%; font-size:18px; background:transparent; margin:32px";

const b = dv.el("div", "");

p.onkeyup = function () {
	disp();
};

function disp(){
	b.innerHTML = "入力された値:" + p.value;
}
```

まず三つinputを横並びで指定する。

let value = "";
 
let inputStyle = "width: 30%; font-size:18px; background:transparent; margin:11px";
 
const p = dv.el("input");
p.placeholder = "年の期間指定";
p.style = inputStyle;
 
const p1 = dv.el("input");
p1.placeholder = "月の期間指定";
p1.style = inputStyle;
 
const p2 = dv.el("input");
p2.placeholder = "日の期間指定";
p2.style = inputStyle;
 
const b = dv.el("div", "");
const b1 = dv.el("div", "");
const b2 = dv.el("div", "");
 
disp();
disp1();
disp2();
 
p.onkeyup = function () {
	disp();
};
 
p1.onkeyup = function () {
	disp1();
};
 
p2.onkeyup = function () {
	disp2();
};
 
function disp(){
	b.innerHTML = "入力された値:" + p.value;
}
 
function disp1(){
	b1.innerHTML = "入力された値:" + p1.value;
}
 
function disp2(){
	b2.innerHTML = "入力された値:" + p2.value;
}

こんな感じでいいかな
ちょっとコードが煩雑になってるけどまあしょうがない

```dataviewjs
let value = "";

let inputStyle = "width: 30%; font-size:18px; background:transparent; margin:11px";

const p = dv.el("input");
p.placeholder = "年の期間指定";
p.style = inputStyle;

const p1 = dv.el("input");
p1.placeholder = "月の期間指定";
p1.style = inputStyle;

const p2 = dv.el("input");
p2.placeholder = "日の期間指定";
p2.style = inputStyle;

const b = dv.el("div", "");
const b1 = dv.el("div", "");
const b2 = dv.el("div", "");

disp();
disp1();
disp2();

p.onkeyup = function () {
	disp();
};

p1.onkeyup = function () {
	disp1();
};

p2.onkeyup = function () {
	disp2();
};

function disp(){
	b.innerHTML = "入力された値:" + p.value;
}

function disp1(){
	b1.innerHTML = "入力された値:" + p1.value;
}

function disp2(){
	b2.innerHTML = "入力された値:" + p2.value;
}
```

これをさっきの収支計算のプログラムに組み込んでいく。

let yVal = "";
let mVal = "";
let dVal = "";
 
let inputStyle = "width: 30%; font-size:18px; background:transparent; margin:11px";
 
const yInput = dv.el("input");
yInput.placeholder = "年の期間指定";
yInput.style = inputStyle;
 
const mInput = dv.el("input");
mInput.placeholder = "月の期間指定";
mInput.style = inputStyle;
 
const dInput = dv.el("input");
dInput.placeholder = "日の期間指定";
dInput.style = inputStyle;
 
yInput.onkeyup = function () {
	yVal = yInput.value;
	renderTag();
};
 
mInput.onkeyup = function () {
	mVal = mInput.value;
	renderTag();
};
 
dInput.onkeyup = function () {
	dVal = dInput.value;
	renderTag();
};
 
let tag = "#仕訳";
 
function renderTag(){
	tag = "#仕訳";
 
	if(yVal !== ""){
		tag += "/" + yVal;
	}
	if(mVal !== ""){
		tag += "/" + mVal;
	}
	if(dVal !== ""){
		tag += "/" + dVal;
	}
	
	tag = tag.replaceAll("/NaN","");
	
	tagDiv.innerHTML = tag;
	executeTable();
}
 
const tagDiv = dv.el("div", "");
tagDiv.innerHTML = tag;
 
//-----------------------------------------------------------
dv.paragraph("---");
//-----------------------------------------------------------
 
const column = ["日付", "内訳", "収入", "支出", "残金"];
 
let table = [];
 
let filesWithTag = dv.pages(tag);
let files = Array.from(filesWithTag);
 
let zankin = 0;
let shunyuResult = 0;
let sishutuResult = 0;
 
createTable();
 
function executeTable(){
	let a = dv.table(column, table);
}
 
function createTable(){
	for(let file of files){
		getShunyu(file);
		getSishutu(file);
	}
	
	addListItem("合計", "", shunyuResult, sishutuResult, zankin);
	
	executeTable();
}
 
function getShunyu(file){
	if(typeof file.収入 === "undefined"){
		return;
	}
	else if(file.収入.constructor === String){
		let item = file.収入.split(":");
		calcZankin("shunyu", item[1]);
		addListItem(file.file.name, item[0], item[1], 0, zankin);
		return;
	}
 
	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		calcZankin("shunyu", item[1]);
		
		addListItem(file.file.name, item[0], item[1], 0, zankin);
	}
}
 
function getSishutu(file){
	if(typeof file.支出 === "undefined"){
		return;
	}
	else if(file.支出.constructor === String){
		let item = file.支出.split(":");
		calcZankin("sishutu", item[1]);
		addListItem(file.file.name, item[0], 0, item[1], zankin);
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		calcZankin("sishutu", item[1]);
		
		addListItem(file.file.name, item[0], 0, item[1], zankin);
	}
}
 
function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}
 
function calcZankin(mode, value){
	let intValue = parseInt(value);
	if(mode == "shunyu"){
		zankin += intValue;
		shunyuResult += intValue;
	}
	else{
		zankin -= intValue;
		sishutuResult += intValue;
	}
}
 
function addListItem(fileName, utiwake, shunyu, sishutu, zankin){
	let linkedFileName = "[[" + fileName + "]]";
	let item = [linkedFileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}

ちょっと動的にテーブルを変更する方法がわからないわ

これ見てもあんまりいい感じにならなかった

metabind使うといいかもしれない

正直ちょっとお手上げだから
中身のコード変えていく感じでやっていくほうにシフトしたほうがいいのかな??

const today = new Date();
let currentMonth = today.getMonth() + 1;
if(currentMonth < 10) currentMonth = '0' + currentMonth;
 
//------------------------------
const column = ["日付", "内訳", "収入", "支出", "残金"];
 
let table = [];
 
let tag = "#仕訳/2024/" + currentMonth;
 
let filesWithTag = dv.pages(tag);
let files = Array.from(filesWithTag);
 
let zankin = 0;
let shunyuResult = 0;
let sishutuResult = 0;
 
dv.paragraph("**使用しているタグ** : " + tag);
createTable();
 
function createTable(){
	for(let file of files){
		getShunyu(file);
		getSishutu(file);
	}
	
	addListItem("合計", "", shunyuResult, sishutuResult, zankin);
	
	dv.table(column, table);
}
 
function getShunyu(file){
	if(typeof file.収入 === "undefined"){
		return;
	}
	else if(file.収入.constructor === String){
		let item = file.収入.split(":");
		calcZankin("shunyu", item[1]);
		addListItem(file.file.name, item[0], item[1], 0, zankin);
		return;
	}
 
	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		calcZankin("shunyu", item[1]);
		
		addListItem(file.file.name, item[0], item[1], 0, zankin);
	}
}
 
function getSishutu(file){
	if(typeof file.支出 === "undefined"){
		return;
	}
	else if(file.支出.constructor === String){
		let item = file.支出.split(":");
		calcZankin("sishutu", item[1]);
		addListItem(file.file.name, item[0], 0, item[1], zankin);
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		calcZankin("sishutu", item[1]);
		
		addListItem(file.file.name, item[0], 0, item[1], zankin);
	}
}
 
function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}
 
function calcZankin(mode, value){
	let intValue = parseInt(value);
	if(mode == "shunyu"){
		zankin += intValue;
		shunyuResult += intValue;
	}
	else{
		zankin -= intValue;
		sishutuResult += intValue;
	}
}
 
function addListItem(fileName, utiwake, shunyu, sishutu, zankin){
	let linkedFileName = "[[" + fileName + "]]";
	let item = [linkedFileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}

最終的にこんな感じになった

ちょっとこれ繰り越しも入れとこう

const today = new Date();
let curMonth = today.getMonth() + 1;
let befMonth = today.getMonth();
if(curMonth < 10) curMonth = '0' + curMonth;
if(befMonth < 10) befMonth = '0' + befMonth;
 
//------------------------------------------------------------
const column = ["日付", "内訳", "収入", "支出", "残金"];
 
let table = [];
 
let curTag = "#仕訳/2024/" + curMonth;
let befTag = "#仕訳/2024/" + befMonth;
 
let curFilesWithTag = dv.pages(curTag);
let curFiles = Array.from(curFilesWithTag);
 
let befFilesWithTag = dv.pages(befTag);
let befFiles = Array.from(befFilesWithTag);
 
let zankin = 0;
let shunyuResult = 0;
let sishutuResult = 0;
 
//render
dv.paragraph("**使用しているタグ** : " + curTag);
createTable();
 
//------------------------------------------------------------
 
function calcKurikoshi(){
	for(let file of befFiles){
		getShunyu(file, false);
	}
	
	addListItem(true, "繰越", befMonth + "月からの繰越", zankin, 0, 0);
}
 
//-----------------------------------------------------------
 
zankin = 0;
shunyuResult = 0;
sishutuResult = 0;
 
function createTable(){
	calcKurikoshi();
 
	for(let file of curFiles){
		getShunyu(file, true);
		getSishutu(file, true);
	}
	
	addListItem(true, "合計", "", shunyuResult, sishutuResult, zankin);
	
	dv.table(column, table);
}
 
function getShunyu(file, isRender){
	if(typeof file.収入 === "undefined"){
		return;
	}
	else if(file.収入.constructor === String){
		let item = file.収入.split(":");
		calcZankin("shunyu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0],
			item[1],
			0,
			zankin
		);
		return;
	}
 
	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		calcZankin("shunyu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0],
			item[1],
			0,
			zankin
		);
	}
}
 
function getSishutu(file, isRender){
	if(typeof file.支出 === "undefined"){
		return;
	}
	else if(file.支出.constructor === String){
		let item = file.支出.split(":");
		calcZankin("sishutu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0], 
			0, 
			item[1], 
			zankin
		 );
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		calcZankin("sishutu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name), 
			item[0], 
			0, 
			item[1], 
			zankin
		);
	}
}
 
function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}
 
function calcZankin(mode, value){
	let intValue = parseInt(value);
	if(mode == "shunyu"){
		zankin += intValue;
		shunyuResult += intValue;
	}
	else{
		zankin -= intValue;
		sishutuResult += intValue;
	}
}
 
function addListItem(isRender, fileName, utiwake, shunyu, sishutu, zankin){
	if(!isRender) return;
	let item = [fileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}
 
function convertLinkedFile(fileName){
	return "[[" + fileName + "]]";
}

できた!

合計のところ強調してみた

const today = new Date();
let curMonth = today.getMonth() + 1;
let befMonth = today.getMonth();
if(curMonth < 10) curMonth = '0' + curMonth;
if(befMonth < 10) befMonth = '0' + befMonth;
 
//------------------------------------------------------------
const column = ["日付", "内訳", "収入", "支出", "残金"];
 
let table = [];
 
let curTag = "#仕訳/2024/" + curMonth;
let befTag = "#仕訳/2024/" + befMonth;
 
let curFilesWithTag = dv.pages(curTag);
let curFiles = Array.from(curFilesWithTag);
 
let befFilesWithTag = dv.pages(befTag);
let befFiles = Array.from(befFilesWithTag);
 
let zankin = 0;
let shunyuResult = 0;
let sishutuResult = 0;
 
//render
dv.paragraph("**使用しているタグ** : " + curTag);
createTable();
 
//------------------------------------------------------------
 
function calcKurikoshi(){
	for(let file of befFiles){
		getShunyu(file, false);
	}
	
	addListItem(true, "繰越", befMonth + "月からの繰越", zankin, 0, 0);
}
 
//-----------------------------------------------------------
 
zankin = 0;
shunyuResult = 0;
sishutuResult = 0;
 
function createTable(){
	calcKurikoshi();
 
	for(let file of curFiles){
		getShunyu(file, true);
		getSishutu(file, true);
	}
	
	addListItem(true, "", "");
	addListItem(
		true, 
		"###### 合計", 
		"", 
		"###### " + shunyuResult, 
		"###### " + sishutuResult, 
		"###### " + zankin
	);
	
	dv.table(column, table);
}
 
function getShunyu(file, isRender){
	if(typeof file.収入 === "undefined"){
		return;
	}
	else if(file.収入.constructor === String){
		let item = file.収入.split(":");
		calcZankin("shunyu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0],
			item[1],
			0,
			zankin
		);
		return;
	}
 
	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		calcZankin("shunyu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0],
			item[1],
			0,
			zankin
		);
	}
}
 
function getSishutu(file, isRender){
	if(typeof file.支出 === "undefined"){
		return;
	}
	else if(file.支出.constructor === String){
		let item = file.支出.split(":");
		calcZankin("sishutu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0], 
			0, 
			item[1], 
			zankin
		 );
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		calcZankin("sishutu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name), 
			item[0], 
			0, 
			item[1], 
			zankin
		);
	}
}
 
function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}
 
function calcZankin(mode, value){
	let intValue = parseInt(value);
	if(mode == "shunyu"){
		zankin += intValue;
		shunyuResult += intValue;
	}
	else{
		zankin -= intValue;
		sishutuResult += intValue;
	}
}
 
function addListItem(isRender, fileName, utiwake, shunyu, sishutu, zankin){
	if(!isRender) return;
	let item = [fileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}
 
function convertLinkedFile(fileName){
	return "[[" + fileName + "]]";
}

なんか繰り越し計算にバグがあったから修正した

```dataviewjs
const today = new Date();
let curMonth = today.getMonth() + 1;
let befMonth = today.getMonth() + 0;
if(curMonth < 10) curMonth = '0' + curMonth;
if(befMonth < 10) befMonth = '0' + befMonth;

//------------------------------------------------------------
const column = ["日付", "内訳", "収入", "支出", "残金"];

let table = [];

let curTag = "#仕訳/2024/" + curMonth;
let befTag = "#仕訳/2024/" + befMonth;

let curFilesWithTag = dv.pages(curTag);
let curFiles = Array.from(curFilesWithTag);

let befFilesWithTag = dv.pages(befTag);
let befFiles = Array.from(befFilesWithTag);

let zankin = 0;
let shunyuResult = 0;
let sishutuResult = 0;

//render
dv.paragraph("**使用しているタグ** : " + curTag);
createTable();

//------------------------------------------------------------

function calcKurikoshi(){
	for(let file of befFiles){
		getShunyu(file, false);
		getSishutu(file, false);
	}
	
	addListItem(true, "繰越", befMonth + "月からの繰越", zankin, 0, 0);
}

//-----------------------------------------------------------

function createTable(){
	calcKurikoshi();
	
	shunyuResult = zankin;
	sishutuResult = 0;

	for(let file of curFiles){
		getShunyu(file, true);
		getSishutu(file, true);
	}
	
	addListItem(true, "", "");
	addListItem(
		true, 
		"###### 合計", 
		"", 
		"###### " + shunyuResult, 
		"###### " + sishutuResult, 
		"###### " + zankin
	);
	
	dv.table(column, table);
}

function getShunyu(file, isRender){
	if(typeof file.収入 === "undefined"){
		return;
	}
	else if(file.収入.constructor === String){
		let item = file.収入.split(":");
		calcZankin("shunyu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0],
			item[1],
			0,
			zankin
		);
		return;
	}

	for(let shunyu of file.収入){
		let item = shunyu.split(":");
		item = combineUniData(item);
		calcZankin("shunyu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0],
			item[1],
			0,
			zankin
		);
	}
}

function getSishutu(file, isRender){
	if(typeof file.支出 === "undefined"){
		return;
	}
	else if(file.支出.constructor === String){
		let item = file.支出.split(":");
		calcZankin("sishutu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name),
			item[0], 
			0, 
			item[1], 
			zankin
		 );
		return;
	}
	
	for(let sishutu of file.支出){
		let item = sishutu.split(":");
		item = combineUniData(item);
		calcZankin("sishutu", item[1]);
		
		addListItem(
			isRender,
			convertLinkedFile(file.file.name), 
			item[0], 
			0, 
			item[1], 
			zankin
		);
	}
}

function combineUniData(item){
	if(item[0].length !== 1) return item;
	return item.join();
}

function calcZankin(mode, value){
	let intValue = parseInt(value);
	if(mode == "shunyu"){
		zankin += intValue;
		shunyuResult += intValue;
	}
	else{
		zankin -= intValue;
		sishutuResult += intValue;
	}
}

function addListItem(isRender, fileName, utiwake, shunyu, sishutu, zankin){
	if(!isRender) return;
	let item = [fileName, utiwake, shunyu, sishutu, zankin];
	table.push(item);
}

function convertLinkedFile(fileName){
	return "[[" + fileName + "]]";
}
```

これ使い続けるうちにわかってきたんだけどなんかObisidian側の使用で更新されたファイルが最新のものっていう扱いを受けるらしい
これでどういう不具合が出るかっていうと時系列データがめちゃくちゃになる
これを回避するには最初にデイリーノートを時系列順にソートする必要がある。
これが結構難しいかも
sort関数使用できないから自分でどうにかしないと

繰り越しがようやく実装できた!
なんかDailyNoteTemplateに1日の時だけ、前月の残金を書くようにしたからそれで、できるようになた

<%*
function isStartOfMonth(date) { 
	return date.getDate() === 1; 
}
 
function getFilesByTag(targetTag) {
  try {
    const filesWithTag = [];
    const normalizedTargetTag = targetTag.startsWith('#') ? targetTag : '#' + targetTag;
    
    const files = app.vault.getMarkdownFiles();
    for (const file of files) {
      const fileCache = app.metadataCache.getFileCache(file);
      if (!fileCache) continue;
      
      const fileTags = fileCache.tags ? fileCache.tags.map(t => t.tag) : [];
      const frontmatterTags = fileCache.frontmatter?.tags || [];
      const normalizedFrontmatterTags = (Array.isArray(frontmatterTags) 
        ? frontmatterTags 
        : [frontmatterTags]
      ).map(tag => tag.startsWith('#') ? tag : '#' + tag);
      
      const allFileTags = [...fileTags, ...normalizedFrontmatterTags];
      
      const hasMatchingTag = allFileTags.some(tag => tag.startsWith(normalizedTargetTag));
      if (hasMatchingTag) {
        filesWithTag.push(file);
      }
    }
    
    return filesWithTag;
    
  } catch (error) {
    console.error("ファイル取得エラー:", error);
    new Notice("ファイルの取得中にエラーが発生しました: " + error.message);
    return [];
  }
}
 
async function getShunyu(file){
	try {
		const content = await app.vault.read(file);
		// インラインフィールド [収入::項目:金額] の形式を抽出
		const shunyuPattern = /\[収入::([^:\]]+):(\d+)\]/g;
		let match;
		
		while ((match = shunyuPattern.exec(content)) !== null) {
			const utiwake = match[1].trim();
			const value = match[2].trim();
			calcZankin("shunyu", value);
		}
	} catch (error) {
		console.error("収入取得エラー:", file.path, error);
	}
}
 
async function getSishutu(file){
	try {
		const content = await app.vault.read(file);
		// インラインフィールド [支出::項目:金額] の形式を抽出
		const sishutuPattern = /\[支出::([^:\]]+):(\d+)\]/g;
		let match;
		
		while ((match = sishutuPattern.exec(content)) !== null) {
			const utiwake = match[1].trim();
			const value = match[2].trim();
			calcZankin("sishutu", value);
		}
	} catch (error) {
		console.error("支出取得エラー:", file.path, error);
	}
}
 
function combineUniData(item){
	if(item.length > 1){
		const value = item[item.length - 1].trim();
		const utiwake = item.slice(0, item.length - 1).join(":").trim();
		return [utiwake, value];
	}
	return ["不明", 0];
}
 
let zankin = 0;
 
function calcZankin(mode, value){
	let intValue = parseInt(value);
	if(mode == "shunyu"){
		zankin += intValue;
	}
	else{
		zankin -= intValue;
	}
}
 
if(isStartOfMonth(today)) {
	zankin = 0;
	
	const currentYear = today.getFullYear();
	const curMonth = (today.getMonth() + 1).toString().padStart(2, '0');
	const lastMonthDate = new Date(today);
	lastMonthDate.setMonth(today.getMonth() - 1);
	const lastMonthYear = lastMonthDate.getFullYear();
	const befMonth = (lastMonthDate.getMonth() + 1).toString().padStart(2, '0');
	const befTag = "#仕訳/" + lastMonthYear + "/" + befMonth;
	const befFiles = getFilesByTag(befTag)
 
	for(let file of befFiles){
		await getShunyu(file); 
		await getSishutu(file);
	}
 
	tR += "[収入::前月繰り越し:" + zankin + "]"
}
%>

sortもこれでできた!

curFiles.sort((a, b) => { const dateA = new Date(a.file.name); 
const dateB = new Date(b.file.name); return dateA - dateB; });