6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

事務系で役立つかもしれないJavaScript - Excel編

Posted at

初投稿です。
ちゃんと書けたかな?

概要

VBAェ...
Excel表をイマドキなJavaScriptで何とかする為の、WebApplicationの自分用テンプレートです。

経緯

事務作業でExcelをこねくり回す時、今更VBA...と思ったのがきっかけ。

"表は2次元配列にしてしまえば勝ち"
というパワープレイ思考をもとに、最近かじり始めたJavaScriptで、勉強も兼ねて書いてみる事にしました。

残念ながら、日本社会において絶対神Excelから逃れる事は不可能なので、せめてもの足掻き。

決め事

  • カンマ区切CSV(UTF-8)のみ
  • xlsx/csvの相互変換は手動で済ます
  • 素のjsでやりきる
  • 最新版Chromeで使う

色々と決め打ちが多いですが、その分コードはかなり簡素化されてると思います。

中身

JavaScript
hoge.js
// onchange: 読込ファイル名表示
function displayFileName(type){
    if(document.getElementById(type).files[0]){
        document.getElementById(type + "_name").innerHTML = document.getElementById(type).files[0].name;
    }else{
        document.getElementById(type + "_name").innerHTML = "";
    }
}

// メインプロセス
async function executeProcess(){

    const json = new Object();
    const csv = new Array();

    await readFile(document.getElementById("json_config").files[0])
        .then((result)=>{
            json.config = JSON.parse(result)
        });
    await readFile(document.getElementById("csv_table1").files[0])
        .then((result)=>{
            csv.table1 = parseCsv(result);
        });
    // 2次元配列化完了
    // オマケでJSONも取り込んでます

    // ココにお好みの処理を・・・

    // 処理後
    downloadFile(json.config, "json-config.csv");
    downloadFile(csv.table1, "csv-table1.csv");
}


// ファイル読込
function readFile(file){
    return new Promise((resolve, reject)=>{
        const reader = new FileReader();
        reader.onload = ()=>{
            resolve(reader.result);
        }
        reader.onerror = (event)=>{
            reject(event);
        }
        reader.readAsText(file);
    });
}

// ダウンロード
function downloadFile(body, name){
    // const bom = "\uEFBBBF";
    const link = document.createElement("a");
    link.href = URL.createObjectURL(new Blob([body], {type: "text/plain"}));
    link.download = name;
    link.click();
}

// CSV分解
function parseCsv(text){
    const csv = new Array();
    const line = text.split("\r\n");
    for(let i = 0; i < line.length; i++){
        csv[i] = line[i].split(',');
    }
    return csv;
}

// CSV結合
function joinCsv(csv){
    let text = new String();
    for(let i = 0; i < csv.length; i++){
        text += csv[i].join(',');
        text += "\r\n"
    }
    return text;
}
HTML
hoge.html
<!DOCTYPE html>
<html lang="ja">

    <head>
        <meta charset="utf-8">
        <title>タイトル</title>
    </head>

    <body>
        <p><table>
            <tr>
                <td class="description">
                    テキストを入力
                </td>
                <td>
                    <input type="text" id="text_input" class="text text-search" placeholder="hoge"/>
                </td>
            </tr>
        </table></p>

        <p><table>
            <tr>
                <td>
                    <label class="hide button button-file">JSONを選択
                        <input type="file" id="json_config" accept=".json" onchange="displayFileName('json_config');"/>
                    </label>
                    <span id="json_config_name" class="description"/>
                </td>
            </tr>
            <tr>
                <td>
                    <label class="hide button button-file">CSVを選択
                        <input type="file" id="csv_table1" accept=".csv" onchange="displayFileName('csv_table1');"/>
                    </label>
                    <span id="csv_table1_name" class="description"/>
                </td>
            </tr>
        </table></p>

        <p><table>
            <tr>
                <td>
                    <label class="hide button button-execute">実行
                        <button onclick="executeProcess();"/>
                    </label>
                </td>
            </tr>
        </table></p>

    </body>
</html>
CSS
hoge.css
/***** フォーム隠蔽: input *****/
.hide > input {
    display: none;
}

/***** フォーム隠蔽: button *****/
.hide > button {
    display: none;
}

/***** テキスト: 説明文 *****/
.description {
    user-select: none;
}

/***** テキストボックス: 共通 *****/
input.text {
    cursor: text;
    display: inline-block;
    font-size: 14px;
    height: 1.5em;
    border:solid 1px #9f9f9f;
    border-radius: 4px;
}

/***** テキストボックス - カラー: ホバー *****/
input.text-search:hover {
    border:solid 1px #0fb920;
}

/***** ボタン: 共通 *****/
label.button {
    user-select: none;
    cursor: pointer;
    display: inline-block;
    padding: 0.1em 0.4em;
    font-size: 14px;
    text-decoration: none;
    border-radius: 4px;
    transition: 0.2s;
}

/***** ボタン - カラー: ファイル *****/
label.button-file {
    color: #cf33dd;
    border: solid 2px #cf33dd;
    background: white;
}
label.button-file:active {
    color: white;
    background: #cf33dd;
}

/***** ボタン - カラー: 実行 *****/
label.button-execute {
    color: #1c9ce6;
    border: solid 2px #1c9ce6;
    background: white;
}
label.button-execute:active {
    color: white;
    background: #1c9ce6;
}

/***** ボタン: トグル *****/
input.toggle {
    position: absolute;
    margin-left: -9999px;
}
input.toggle + label {
    user-select: none;
    display: block;
    position: relative;
    cursor: pointer;
    outline: none;
    user-select: none;
    padding: 2px;
    height: 18px;
    width: 36px;
    background-color: #9f9f9f;
    border-radius: 36px;
    transition: 0.2s;
}
input.toggle + label:before, input.toggle + label:after {
    display: block;
    position: absolute;
    content: "";
}
input.toggle + label:before {
    top: 2px;
    left: 2px;
    bottom: 2px;
    right: 2px;
    background-color: #ffffff;
    border-radius: 36px;
    transition: 0.2s;
}
input.toggle + label:after {
    top: 4px;
    left: 4px;
    bottom: 4px;
    width: 14px;
    background-color: #9f9f9f;
    border-radius: 36px;
    transition: 0.2s;
}
input.toggle:checked + label {
    background-color: #0fb920;
}
input.toggle:checked + label:after {
    margin-left: 18px;
    background-color: #0fb920;
}

振り返り

  • FileReader便利
  • Promiseの使い方は何となく掴んだ
  • アローはとりあえず即時関数として使えば良いのかな?

ファイル編集は今までC#で行っていたのですが、簡単な処理ならjsでも全然行けますね。

コンパイルやUI作る手間がだいぶ省けるので、ちょっとしたオートメーション化に活用できそうです。
(VSCodeだけで完結可能なのは嬉しい)

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?