💸
確定申告の外国税額控除のためにウェルスナビのPDFをparseしてみた
はじめに
確定申告には外国税額控除というものがある。

私はウェルスナビを使っているのだが、ウェルスナビ発行のPDFを見ながら外国税額控除を入力するのが面倒だったので、(3つくらい入力して慣れれば別にそうでもない説あり)
- 全てのPDFを全部parseして入力に必要なものをCSVとして出力し、
- その項目をコピーして各項目にペースト
をやってみることにした。
parseしてみる

PDFをparseすると、テキスト部分は配列となって取得出来る。
まず、数ファイルを1ファイルずつparseして見比べてみて、テキスト部分の配列とウェルスナビのPDFの項目の対応を出してみる。
今回はPDF.jsを利用した。
// node v17.0.1
const fs = require('fs');
// "pdfjs-dist": "^2.13.216"
const pdfjsLib = require("pdfjs-dist/legacy/build/pdf");
async function GetTextFromPDF(path, pageNumber) {
let doc = await pdfjsLib.getDocument(path).promise;
let page = await doc.getPage(pageNumber);
let content = await page.getTextContent();
let strings = content.items.map(function(item) {
return item.str;
});
return strings;
}
// PDFファイルはpdfディレクトリに置いてある
let path = 'pdf/2020210105.pdf';
GetTextFromPDF(path, 1).then(data => data.forEach((v, i) => console.log(`i: ${i}, v: ${v}`)));
| 配列index | データ例 | ウェルスナビPDF対応箇所 | 確定申告入力欄対応箇所 |
|---|---|---|---|
| 0 | (00000-0878-1) | 7 | |
| 1 | 銘柄 | ||
| 2 | 連 絡 先 | ||
| 3 | T E L | ||
| 4 | 権利区分 | ||
| 5 | |||
| 6 | 通貨区分 | ||
| 7 | |||
| 8 | 支払方法 | ||
| 9 | |||
| 10 | 現地支払日 | ||
| 11 | 国内支払日 | ||
| 12 | 残高基準日 | ||
| 13 | 2021年01月06日 | 6 | 4, 5 |
| 14 | お預り数量 | ||
| 15 | |||
| 16 | 現地税込金額 | ||
| 17 | |||
| 18 | 現地源泉税率 | ||
| 19 | |||
| 20 | 現地源泉税額 | ||
| 21 | |||
| 22 | 現地税引き後金額 | ||
| 23 | 単位当りの | ||
| 24 | 2020年12月28日 | 5 | |
| 25 | 支払基準日 | ||
| 26 | |||
| 27 | 支払レート | ||
| 28 | 部店 | ||
| 29 | |||
| 30 | 扱者 | ||
| 31 | |||
| 32 | 口座番号 | ||
| 33 | 123 | 1 | |
| 34 | |||
| 35 | 456 | 2 | |
| 36 | |||
| 37 | 1234567 | 3 | |
| 38 | |||
| 39 | 苗 字 | 4 | |
| 40 | |||
| 41 | 名 前 | 4 | |
| 42 | |||
| 43 | 様 | ||
| 44 | 国内税引き前金額 | ||
| 45 | |||
| 46 | 上段:外貨 | ||
| 47 | 下段:円貨 | ||
| 48 | 国内源泉所得税額 | ||
| 49 | |||
| 50 | お受取り金額 | ||
| 51 | 上段:外貨 | ||
| 52 | (下記Aより) | ||
| 53 | 国内源泉住民税額 | ||
| 54 | (下記Bより) | ||
| 55 | 下段:円貨 | ||
| 56 | 上段:外貨 | ||
| 57 | 下段:円貨 | ||
| 58 | 上段:外貨 | ||
| 59 | 下段:円貨 | ||
| 60 | [国内源泉税額の計算明細 及び 申告用明細] | ||
| 61 | 現地源泉税率 | ||
| 62 | 源泉徴収レート | ||
| 63 | |||
| 64 | 国内課税対象金額(円貨) | ||
| 65 | 源泉徴収レート・・・現地保管機関が配当等を受領した日又は | ||
| 66 | 権利の確定ごとに公表される現地支払開始日の為替レート | ||
| 67 | A:国内源泉所得税額(円貨) | ||
| 68 | |||
| 69 | B:国内源泉住民税額(円貨) | ||
| 70 | 源泉徴収基準日 | ||
| 71 | (申告円換算日) | ||
| 72 | 制限税率 | ||
| 73 | (USD) | ||
| 74 | |||
| 75 | 還付請求金額(外貨) | ||
| 76 | 2020-12-30 | 24 | |
| 77 | |||
| 78 | 103.25 | 25 | |
| 79 | ① | ||
| 80 | 0.7818 | 13 | |
| 81 | Vanguard | 7 | |
| 82 | |||
| 83 | VTI | 7 | |
| 84 | |||
| 85 | ETF | 7 | |
| 86 | |||
| 87 | 配当金 | 8 | 2 |
| 88 | |||
| 89 | 米ドル | 9 | 10, 13 |
| 90 | |||
| 91 | 円貨払い | 10 | |
| 92 | |||
| 93 | 2020-12-30 | 24 | |
| 94 | 65.433 | 12 | |
| 95 | 配当金 | ||
| 96 | 51.15 | 14? | 9 |
| 97 | |||
| 98 | 10.00% | 15? | |
| 99 | |||
| 100 | 5.12 | 16 | 12 |
| 101 | |||
| 102 | 46.03 | 17 | |
| 103 | 2021-01-04 | 18 | |
| 104 | |||
| 105 | 103.12 | 19 | |
| 106 | <ご説明> | ||
| 107 | |||
| 108 | 為替レートについて | ||
| 109 | ② 支払レート | ||
| 110 | |||
| 111 | ・・・弊社が配当等の受領を確認した日の為替レート又は、予約為替レート | ||
| 112 | 4,746 | 20 | |
| 113 | 内容をご確認のうえ、ご不明の点がございましたら、すみやかに弊社連絡先まで直接ご連絡ください。 | ||
| 114 | 727 | 21? | |
| 115 | |||
| 116 | 237 | 22? | |
| 117 | |||
| 118 | 3,782 | 23 | |
| 119 | お 客 様 サ ポ ー ト | ||
| 120 | 4,752 | 26 | |
| 121 | |||
| 122 | 0.00 | 29 | |
| 123 | 727 | 27? | |
| 124 | |||
| 125 | 237 | 28? | |
| 126 | 現地課税対象金額(外貨) | ||
| 127 | |||
| 128 | 現地税込金額(円貨) | ||
| 129 | 現地税込金額(外貨)×源泉レート | ||
| 130 | |||
| 131 | 外税控除の対象となる金額 | ||
| 132 | 10.00% | 30? | |
| 133 | 0 3 - 6 6 3 2 - 9 5 7 8 | ||
| 134 | 10.00% | 31? | |
| 135 | 2021年01月05日 | ||
| 136 | (外貨) | ||
| 137 | 51.15 | 32? | |
| 138 | (通貨コード) | ||
| 139 | (外貨) | ||
| 140 | |||
| 141 | (外貨) | ||
| 142 | (外貨) | ||
| 143 | 作成 | ||
| 144 | (銘柄コード) | ||
| 145 | (USD) | ||
| 146 | (USD) | ||
| 147 | 5,281 | 33 | 11 |
| 148 | |||
| 149 | 528 | 34 | 14 |
| 150 | 外国証券 | ||
| 151 | |||
| 152 | 利金・分配金・償還金・配当金等のお知らせ |
- PDF上で同じ数字が入っている欄は見分けが付かないため
?としている - 自分の2021年分のPDFは、parseすると配列長が全て同じだった。奇跡的に銘柄名も「Vanguard VTI ETF」、「Vanguard VWO ETF」のように全て3単語で構成されていた
CSVにする
上記で確定申告で使えるテキスト配列のindexが分かったので、その部分をCSVとして出力する。区切り文字はタブ文字で。
const fs = require('fs');
const pdfjsLib = require("pdfjs-dist/legacy/build/pdf");
async function GetTextFromPDF(path, pageNumber) {
let doc = await pdfjsLib.getDocument(path).promise;
let page = await doc.getPage(pageNumber);
let content = await page.getTextContent();
let strings = content.items.map(function(item) {
return item.str;
});
return strings;
}
fs.readdir('pdf', (err, files) => {
files.forEach(async file => {
// PDFファイルはpdfディレクトリ配下に置いてある
let doc = await pdfjsLib.getDocument(`pdf/${file}`).promise;
for (let i = 1; i <= doc.numPages; i++) {
GetTextFromPDF(`pdf/${file}`, i).then(data => {
console.log(
[
data[13],
data[87],
data[89],
data[96],
data[100],
data[147],
data[149]
].join('\t')
);
});
}
});
});
result
2021年01月06日 配当金 米ドル 51.15 5.12 5,281 528
2021年02月10日 配当金 米ドル 3.01 0.30 317 31
2021年03月10日 配当金 米ドル 3.18 0.32 344 34
.
.
おわりに
ほんの少しだけ入力が楽になった気はするが、人間が手入力すると入力ミスが発生する可能性がある。
そもそも、確定申告書作成コーナーがXML等を読み込ませて自動入力出来るように進化して欲しい。そしてウェルスナビ等がそのXMLを提供して欲しい。
その他
- 確定申告書作成コーナーで拡張機能やJavaScriptで自動入力する手もあるだろうが、id要素の重複がフツーにあったので色々大変そう(そもそもあのページで拡張機能動くかは不明)
-
pdf-parse
^1.1.1も使ってみたが、口座番号等の一部テキストが連結されて取得されてしまったので却下 -
PDF-Scrape
^0.9.5も使ってみた。CLIでカジュアルにparse出来る点はいいのだが、こちらはPDF.jsとは違った場所でテキストが分割されていたり、氏名の間の半角スペースがtrimされていたため、他にも何かあるかもしれないと考えた結果、却下
Discussion