質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

2回答

4627閲覧

平成や令和等の和暦を西暦に変換するコードをきれいにしたい

zigutabi

総合スコア57

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2020/04/03 02:03

編集2020/04/03 02:36

###現状
スプレッドシート上にある和暦のデータを西暦に変換したのですが、コードが場当たり的で効率化したいです。
Excelであれば必要がないのですが、スプレッドシートでは日本語書式に対応していないことに加えて、徐々にExcelからスプレットシートに移行する流れがあるため、その対策として組みました。

###ソースコード上の課題
和暦で使われる令和と平成を変換したのですが、令和なら令和、平成なら平成と直接記述しているため、応用性が低くなったように感じます。取得元が最近になって始まった制度のため、平成と令和しかないのですが、この書き方だと拡張性に問題があると思いました。
データとコートは以下のものになります。

年月日列2列3
平成25年10月1日
平成26年4月1日
平成27年7月1日
平成28年6月1日
平成29年10月1日
平成30年9月1日
令和元年11月1日
令和2年3月1日
※年月日の列を直接選択
const ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); function myfunc(){ let rng = ss.getActiveRange(); if(rng.getNumColumns() > 1) { Browser.msgBox("1列のみ選択してください"); return; } let strList = rng.getValues(); let setList = []; this.str = ""; for(str of strList){ this.str = str.toString(); this.str = changeKeyWord(this.str); this.str = changeWarekiYear(this.str); setList.push([this.str]); } rng.setValues(setList); } const changeKeyWord = function(str) { if(str.match("令和") === null || str.match("平成") === null){ Browser.msgBox("対象外の列か既に修正済みのデータが選択されています。"); return; } const yearWordMap = { '元年':'1/', '年':'/', '月':'/', '日':'' } const reg = new RegExp('(' + Object.keys(yearWordMap).join('|') + ')', 'g'); return str.replace(reg, (match) => { return yearWordMap[match]; }); } const changeWarekiYear = function(str) { let ymd = str.split('/'); let yy = ymd[0].split(/\d/g); ymd[0] = ymd[0].substr(2, ymd[0].length -2); yy = yy[0].replace("令和", "2019").replace("平成", "1989"); return Number(yy) + Number(ymd[0]) + "/" + ymd[1] + "/" + ymd[2]; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/04/03 02:07

拡張性の問題を考えるのは、「過去」と「未来」と、どちらでしょうか?
kaina

2020/04/03 02:30

タイトルが平成や令和等を和暦に変換となっていますが、平成や令和は和暦です。 西暦に変換の間違えでは? 修正してください。
zigutabi

2020/04/03 02:36

タイトルミスりました。 修正しました。
Zuishin

2020/04/03 03:07 編集

取得元の Excel は本当に文字列で入力してるんでしょうか? もしかして文字列で表示されているだけでは?
zigutabi

2020/04/03 09:06

ExcelではなくてWebサイトに書いてある「年月日」をそのままコピペしているだけです。
Zuishin

2020/04/03 09:11

> Excelからスプレットシートに移行する流れがあるため、
zigutabi

2020/04/03 11:29

それは作業環境の流れという意味です。 開発・作業環境がExcelからスプレッドシートに移行するので、日本のみでシリアル値を取得できない和暦をスクリプトで解決しなければならなかったということです。
Zuishin

2020/04/03 11:32 編集

終わってから説明されても。次回質問することがあるなら、他人に伝わる書き方を心掛けましょう。
guest

回答2

0

ベストアンサー

・私なら
Excelでは和暦がサポートされているはずなのでそちらで修正してもってくると思います(できないかもしれないです)

・拡張性
そのプログラムが活用される期間で一体何回修正が必要でしょうか。本当に必要な拡張性ですか? YAGNI を確認したほうがいいと思います。
また、和暦を西暦にすることの和暦を増やすより西暦を和暦に戻すほうが直近の需要がありそうで、かつ難しいです(日付を考慮しないといけないので)。

・もしやるなら
1行目のオブジェクトに別の年号の開始年を入れてください。それだけで動くといいなと期待してます。
セル関数として作ったので、使いかたは B2 セルに =q251048(A2) とかって書いてください。

javascript

1const JPeraStarts = {"昭和":1925,"平成":1989,"令和":2019}; 2const BuilReg = (JPeraStarts) => { 3 return new RegExp(`^(${Object.keys(JPeraStarts).map(e=>`${e}`).join("|")})(元|[0-9]{1,2})年([0-9]{1,2})月([0-9]{1,2})日$`); 4} 5 6const q251048 = (str) => { 7 const format = BuilReg(JPeraStarts); 8 const matches = format.exec(str); 9 if(matches === null) return str; 10 const year = JPeraStarts[matches[1]] + Number((matches[2] === "元" ? 1 : matches[2])) - 1; 11 const month = Number(matches[3]); 12 const date = Number(matches[4]); 13 return new Date(year, month - 1, date); 14}

投稿2020/04/03 04:52

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zigutabi

2020/04/03 14:17 編集

>>Excelでは和暦がサポートされているはずなのでそちらで修正してもってくると思います(できないかもしれないです) Excelの書式変換には和暦が含まれております。 ただ、会社が完全クラウド化を目標にしているため、いずれExcelを使わなくなる大人の事情がありました。 また、if-else以外の分岐に慣れたいと思っているのですが、正規表現にまだ慣れていなかったのでこれを機会に覚えたいと思いました。
zigutabi

2020/04/03 14:22 編集

収集先は和暦なのですが、そのデータを提出する先は西暦で統一しなければなりません。また集めたデータが数十件とあるので選択した範囲を和暦→西暦に一括で直す必要がありました。 和暦・西暦はそんなに頻繁にありませんが、正規表現を使った分岐処理がコードがきれいと記事で読んだことがありました。たった変数1つのためにelseifが続くのは可読性もメンテナンス性も下がります。しかし、ご教授いただいた方法は他にも応用できるので、参考になりました。
zigutabi

2020/04/03 09:05

大変勉強になりました。 replaceするものばかりだと思ったら、一切使わずに成立するのに驚きました。 精進していきたいと思います。
papinianus

2020/04/04 13:33

replaceを使っていないのは、文字列にしたくないからです。日付は日付型にしないとまともに扱えません。
guest

0

考え方だけ。
私だったら変換テーブルを別シートに持っておき、VLOOKUPで西暦を取得する関数を
作って対応します。
そうすることで新元号が追加された場合でも、変換テーブルにデータを追加するだけで良くなります。

日付の妥当性チェックを行う為に西暦の開始年月日を持っておき、西暦変換後の年月日の比較や
元年表記の場合の置換等も入れるようにしましょう。

こちらの参考ページに西暦から和暦への変換関数がありますので、参考にするとよいかと思います。
考え方は同じで行けるはずです。

投稿2020/04/03 02:58

kaina

総合スコア418

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問