2026-02-13

ご訪問をありがとうございます ✨✨✨

八百茄子 は ソフトウェアエンジニア1名による小さな工房です
週末に スキルアップ と 八百茄子 向けのコンテンツ作成に勤しんでおります





ご提供コンテンツ

tools にて
八百茄子 の作成したツールをご紹介しています

knowhow にて、
2x年の組込み系ソフトウェア開発エンジニアとして得た知識・ノウハウに
7年以上 管理職を務めてて得た知識・ノウハウ、
個人開発(ぺーぺー)で得た知識・ノウハウを記録・共有します

エンジニアは技術が命
技術を磨いて、実績を積み上げて、自身の市場価値を高めていきましょう!!


ご挨拶

得られた経験やアウトプットしたコンテンツで
みなさまの誰か一人にでも喜ばれる何かができたらいいな、と思います (・∀・)

子どもたちの未来が少しでもよりよいものとなりますように (*´ω`*)

よろしくお願い致します (´・ω・`)

2026-02-11

json形式のタスク情報から html形式のガントチャートを作成するプログラムを作ってみた

 python で json形式のタスク情報から html形式のガントチャートを作成するプログラムを作ってみました


特に説明はなしです 💦

実際に動かして試してみて楽しんでみてください ('ω')ノシ


ちゃんと動けば、gantt.html が出力されて、ブラウザに読み込ませると下図のようになります (*´ω`*)




ではでは・・・


まずは anaconda 環境に必要なライブラリのインストールする

pip install pandas

pip install plotly


sample.json という名前のタスク情報を記したファイルを作成する

{

  "title": "戦国時代(+450年)",


  "tasks": [

    {

      "id": "task1",

      "name": "織田信長",

      "start": "1984-06-23",

      "end": "2032-06-21",

      "owner": "織田信長",

      "progress": 70,

      "summary": "",

      "memo": "",

      "milestones": []

    },

    {

      "id": "task2",

      "name": "豊臣秀吉",

      "start": "1987-03-17",

      "end": "2048-09-18",

      "owner": "豊臣秀吉",

      "progress": 40,

      "summary": "",

      "memo": "",

      "milestones": [

        {"name": "天下統一", "date": "2040-01-01"}

      ]

    },

    {

      "id": "task3",

      "name": "徳川家康",

      "start": "2043-01-31",

      "end": "2066-06-01",

      "owner": "徳川家康",

      "progress": 90,

      "summary": "",

      "memo": "",

      "milestones": [

        {"name": "征夷大将軍就任", "date": "2053-01-01"},

        {"name": "大坂夏の陣", "date": "2065-01-01"}

      ]

    }

  ]

}


肝心かなめのプログラムはこちらです

 import json

import pandas as pd

import plotly.express as px

import plotly.graph_objects as go

from datetime import datetime


# -----------------------------

# JSON読み込み

# -----------------------------

with open("sample.json", encoding="utf-8") as f:

    root = json.load(f)


TITLE = root["title"]

data = root["tasks"]


rows = []

completed_rows = []

remaining_rows = []

milestones = []


# -----------------------------

# データ整形

# -----------------------------

for t in data:


    start = pd.to_datetime(t["start"]).normalize()

    end = pd.to_datetime(t["end"]).normalize()


    duration = end - start

    progress_end = (start + duration * (t["progress"] / 100)).normalize()


    # hover用情報

    rows.append({

        "Task": t["name"],

        "Start": start,

        "Finish": end,

        "Owner": t["owner"],

        "Summary": t["summary"],

        "Memo": t["memo"],

        "StartStr": start.strftime("%Y-%m-%d"),

        "FinishStr": end.strftime("%Y-%m-%d")

    })


    # 完了部分

    if progress_end > start:

        completed_rows.append({

            "Task": t["name"],

            "Start": start,

            "Finish": progress_end

        })


    # 未完了部分

    if progress_end < end:

        remaining_rows.append({

            "Task": t["name"],

            "Start": progress_end,

            "Finish": end,

            "Owner": t["owner"]

        })


    # マイルストーン

    for ms in t["milestones"]:

        ms_date = pd.to_datetime(ms["date"]).normalize()

        milestones.append({

            "Task": t["name"],

            "Date": ms_date,

            "Label": f'{ms["name"]}\n{ms_date.strftime("%Y-%m-%d")}'

        })


df = pd.DataFrame(rows)

completed_df = pd.DataFrame(completed_rows)

remaining_df = pd.DataFrame(remaining_rows)

ms_df = pd.DataFrame(milestones)


# -----------------------------

# ガント(未完了)

# -----------------------------

fig = px.timeline(

    remaining_df,

    x_start="Start",

    x_end="Finish",

    y="Task",

    color="Owner",

    hover_data=[]

)


fig.update_yaxes(autorange="reversed")


# ★バー枠線なし

fig.update_traces(marker_line_width=0)


# -----------------------------

# hover情報追加

# -----------------------------

for _, r in df.iterrows():

    fig.add_trace(go.Scatter(

        x=[r["Start"]],

        y=[r["Task"]],

        mode="markers",

        marker=dict(size=0),

        showlegend=False,

        hovertemplate=

            f"<b>{r['Task']}</b><br>"

            f"担当: {r['Owner']}<br>"

            f"開始: {r['StartStr']}<br>"

            f"終了: {r['FinishStr']}<br>"

            f"概要: {r['Summary']}<br>"

            f"メモ: {r['Memo']}<extra></extra>"

    ))


# -----------------------------

# 完了バー(グレー)

# -----------------------------

if not completed_df.empty:


    fig_completed = px.timeline(

        completed_df,

        x_start="Start",

        x_end="Finish",

        y="Task"

    )


    for trace in fig_completed.data:

        trace.marker.color = "lightgray"

        trace.marker.line.width = 0

        trace.showlegend = False

        fig.add_trace(trace)


# -----------------------------

# マイルストーン

# -----------------------------

for _, r in ms_df.iterrows():

    fig.add_trace(go.Scatter(

        x=[r["Date"]],

        y=[r["Task"]],

        mode="markers+text",

        marker=dict(size=12, color="red", symbol="diamond"),

        text=r["Label"],

        textposition="top center",

        showlegend=False

    ))


# -----------------------------

# 今日ライン

# -----------------------------

today = pd.to_datetime(datetime.now()).normalize()


fig.add_shape(

    type="line",

    x0=today,

    x1=today,

    y0=0,

    y1=1,

    xref="x",

    yref="paper",

    line=dict(color="black", width=2, dash="dash")

)


fig.add_annotation(

    x=today,

    y=1,

    xref="x",

    yref="paper",

    text="Today",

    showarrow=False,

    yshift=10

)


# -----------------------------

# 軸の日付表示形式

# -----------------------------

fig.update_xaxes(tickformat="%Y-%m-%d")


# -----------------------------

# タイトル

# -----------------------------

fig.update_layout(

    title=TITLE,

    title_x=0.5

)


# -----------------------------

# 出力

# -----------------------------

fig.write_html("gantt.html")

print("gantt.html を出力しました")


これで動かしてみてください ('ω')ノシ
 


 

 

 

 

2026-01-17

ii-wf-taskMng

操作ガイド

会社 あるいは 現場によっては、ショートカット・共有サーバを活用した回覧・ワークフローを行っていることがあろうかと思います

ii-wf-taskMng は ショートカット・共有サーバを活用した回覧・ワークフローのエクスプローラー操作の手間や手数を減らすことで、普段の作業のストレスを軽減し、業務効率アップに貢献するツールです(タスク管理・ランチャーとしても活用頂けます)

こちら( Vector 、 note )からダウンロードできます

ここでは ii-wf-taskMng の操作方法について記載します

まずは、基本操作について記載し、
その後、応用として、具体的なユースケースを記載します


基本操作

ディレクトリを登録する

Browse ボタンからディレクトリを選択し、追加ボタンを押下する





ファイル一覧からファイルを確認する

画面中段のドロップダウンリストAから 「全」 や 「2」 を選択し、
画面中段のドロップダウンリストBでファイルを確認する


※ファイル名の先頭の6桁の数字を期日を示す年月日と認識し、
 「2」であれば、期日が「残り2日まで」となっているものを表示します


ファイルに対して各種操作をする

画面中段のドロップダウンリストから各種操作を選択、実行ボタンで実行する




開く ファイルを開く
ファイルを 済 ディレクトリに移動させる
保留 ファイルを 保留 ディレクトリに移動させる
コピー ファイルを任意のディレクトリにコピーする *1
移動 ファイルを任意のディレクトリに移動する *1
回覧 任意のディレクトリにファイルのショートカットを作成する *1, *2
ショートカット カーボンコピーしてある文字列でショートカットファイルを作成する *1, *2
フルパス ファイルのフルパスをカーボンコピーする
ファイル名 ファイルのファイル名をカーボンコピーする
更新 ファイルの一覧を更新する
ログ 操作ログを記したファイルを開く
*1 任意のフォルダを指定する際、初期に表示されるディレクトリは
 "settings of directory" にて選択されているディレクトリとなります
*2 作成されるファイル名の先頭には "settings of directory" にて選択、
 設定されている文字列が付加されます
 例えば、 26  1  25  豊臣秀吉 である場合のファイル名は下記の通りです
  260125_豊臣秀吉_<実行時の日時情報>_url.lnk


ショートカットファイルを Drag&Drop で作成する

画面中段のエリアにファイルを Drag&Drop する



Drag&Drop した際に作られるショートカットファイルのファイル名の先頭には
"settings of directory" にて選択、設定されている文字列が付加されます

 例えば、 26  1  25  豊臣秀吉 である場合のファイル名は下記の通りです
  260125_豊臣秀吉_<Drag&Drop したファイルのファイル名>.lnk



ユースケース

回覧依頼

パターン①:実態ファイルを使って Drag&Drop でショートカットを作成・配置する




パターン②:選択したファイルでショートカットを作成・配置する



パターン③:選択したファイルをコピー(あるいは 移動)で配置する


回覧承認

確認・承認するファイルを 済 ディレクトリに移動させる



タスク管理

回覧ディレクトリではなくタスク用ディレクトリを用意することで、
タスク管理にも活用することができます ✨



ランチャー

よく使うアプリのショートカットを集めたディレクトリを用意することで、
ランチャーとしても活用することができます ✨



その他

TODO 管理や最近よく使うファイル、ブックマーク的な使い方もできると思います
みなさんの発想次第で使い方は自由です


フリーソフトになりますので、どうぞ ご自由に ご活用くださいませ 

こちら( Vector 、 note )からダウンロードできます





2026-01-04

Excel 差分抽出でよくある落とし穴と考え方

Excel 差分抽出でよくある落とし穴と考え方

Excel の差分抽出を Excel で行う 際、
 一見うまくいっているように見えるけど、実は正しく比較できていない
というケースは少なくないです

実務で頻発する落とし穴と、その対策を整理していきます ('ω')ノシ


実務でよくある落とし穴

① 行順が同じ前提で比較してしまう

IF関数やセル比較は、「同じ行=同じデータ」 という前提になります

しかし、実際には、

  • 並び順が変わる
  • 途中に行が追加・削除される

といったことが頻繁に起こります

この状態で単純比較を行うと、
実際には同一データであっても「すべて不一致」と判定されてしまいます ( ノД`)シクシク…

対策

  • 商品コードやIDなど、必ず一致する「キー列」を使う
  • 並び順に依存しない比較方法(XLOOKUP)を選択する


② 空白・0・NULLの違いを見落とす

Excel では、以下は見た目が似ていても意味が異なります

  • 空白セル
  • 0
  • ""(空文字)
  • 数式結果が空白

これを意識せず比較すると、

  • 実際には変更がないのに差分扱いされる
  • 逆に変更を見逃す

といった問題が発生します

対策

  • 比較前にデータの正規化を行う
  • IF関数で TRIMIFERROR を併用する


③ 書式や表示形式の違いに惑わされる

数値と文字列の違い、日付の表示形式の違いなども、差分判定の原因になります

例:

  • 2026/01/012026-01-01
  • 00123123

対策

  • 比較前に表示形式を統一する
  • 文字列/数値の型を意識して揃える


行ズレを防ぐための考え方

行ズレは「Excel 差分」の最大の敵

差分抽出で最も多い失敗原因は、行ズレを考慮していないこと です

そのため、次の考え方が重要です


キー列を必ず用意する

差分抽出を行う場合、以下のような 一意に特定できる列 を必ず用意する

  • 商品コード
  • 顧客ID
  • 管理番号

このキーを基準に、

  • before にあって after にない → 削除
  • after にあって before にない → 追加
  • 両方にあるが内容が違う → 更新

という形で分類する


並び順は「比較後」に整える

比較前に並び替えを頑張る必要はなし

  • 元データはそのまま
  • 差分抽出後の結果表で並び替える

この方が、作業ミスを防ぎやすくなります


少量と大量で手法を使い分ける

データ量推奨手法
数十〜数百行XLOOKUP / COUNTIF
数千行以上Power Query

無理に関数で対応し続けると、
ファイルが重くなり、保守も難しくなります


差分結果を「レポート」としてまとめる考え方

差分抽出の目的は、
「差を見つけること」ではなく「差分を他人に伝えること」 です ✨✨✨

そのため、結果のまとめ方が重要になります


差分結果は3分類に分ける

実務では、次の3つに分類すると分かりやすくなります

  • 新規追加
  • 削除
  • 更新

特に「更新」は、

  • どの項目が
  • どう変わったか

が分かる形にすると、レビューや承認がスムーズになります


差分専用シートを作る

元データを直接加工するのではなく、

  • before
  • after
  • 差分結果

別シートとして分離 するのがおすすめです

これにより、

  • 元データの保全
  • 差分ロジックの再確認
  • 後日の再チェック

が容易になります


色・フラグ・コメントを使い分ける

差分結果の表現方法も重要です

表現用途
目視確認
フラグ(追加/削除/更新)集計・フィルタ
コメント理由・補足説明

「人が見る用」と「集計する用」を意識して設計すると、
実務で非常に使いやすくなります


まとめ

Excel で差分抽出を行う際は、

  • 行順に依存しない設計
  • データの揺れ(空白・型)への配慮
  • 結果を伝えるためのレポート設計

この3点を意識することで、
「動くけど使えない差分」から
「実務で信頼できる差分」へとレベルアップできます

差分抽出の手法そのものだけでなく、
前後の考え方まで含めて設計することが重要 です

を意識して設計すると、
実務で非常に使いやすくなります


参考

Excel の差分抽出を行うツールを用意しておりますので、
是非お試しくださいませ ✨✨✨

https://yaonasu.blogspot.com/2025/11/ii-excel-diff.html
https://yaonasu.blogspot.com/2025/11/ii-exsh-diff.html

2026-01-03

【初心者向け】Excel で差分を抽出する7つの方法

 

【初心者向け】Excel で差分を抽出する7つの方法

〜目的別に選べる7つのパターン解説〜

Excel で作成したデータを更新したあと、

  • どこが変わったのか分からない
  • 前のデータとの差分を確認したい
  • 追加・削除・変更だけを知りたい

と感じたことはありませんか?

本記事では、Excel初心者の方でも理解しやすいように
Excel で差分を抽出する代表的な方法を「パターン別」に整理して解説します


Excel の差分抽出とは?

差分抽出とは、
2つのデータ(更新前・更新後)を比較して、違いを見つけることです

例えば、

  • 商品マスタの更新
  • 月次データの比較
  • システム出力結果の確認

など、実務では頻繁に行われます。

ただし、差分抽出には複数の方法があり、
目的に合わない方法を選ぶと、正しく比較できません


差分抽出の代表的なパターン一覧

まずは、Excelでよく使われる差分抽出の方法を一覧で見てみましょう

No方法特徴
1IF関数で比較最もシンプル
2条件付き書式色で差分を表示
3VLOOKUP / XLOOKUPキーで突合
4COUNTIF / MATCH存在有無の確認
5Power Query大量データ向け
6VBA自動化向け
7外部ツール技術者向け

初心者の方は、1〜4を理解できれば十分 です


方法別:メリット・デメリット比較

次に、それぞれの方法の違いを表で確認します

方法メリットデメリット向いている場面
IF関数簡単・分かりやすい行ズレに弱い同じ形式の表
条件付き書式見た目で確認できる一覧化しにくい目視確認
XLOOKUP行順が違ってもOK関数がやや難しいマスタ比較
COUNTIF追加・削除が分かる内容比較は不可件数チェック
Power Query大量データに強い学習が必要定期作業
VBA自由度が高い難易度が高い自動化
外部ツール高速・正確Excel外作業技術者向け

各パターンの具体的なやり方(初心者向け)

ここからは、よく使われる方法だけを具体的に紹介します


方法1:IF 関数でセルの差分を比較する

概要

同じ行・同じ列構成の2つの表を、セルごとに比較する最も簡単な方法です

やり方
  1. 比較結果用の列を作成

  2. 以下の式を入力

=IF(A2=B2,"一致","不一致")
  1. 下までコピー

向いているケース
  • 行順が完全に同じ
  • 少量データ

方法2:条件付き書式で差分を色表示する

概要

差分を「抽出」するのではなく、色で分かりやすく表示する方法です

やり方
  1. 比較したい範囲を選択

  2. 条件付き書式 → 数式を使用

  3. 数式例(比較先の範囲の一番左で一番上のセル番号が A1 の場合の例)

=A1<>Sheet2!A1
  1. 塗りつぶし色を設定

向いているケース

  • 確認作業だけしたい
  • 印刷前のチェック


方法3:XLOOKUP でマスタ差分を確認する

概要

商品コードなどの「キー」を使って、更新前後の差分を確認する方法です

やり方(例)
=XLOOKUP(A2, before!A:A, before!C:C, "なし")
  • 「なし」=新規追加
  • after にない場合=削除

向いているケース

  • 行順が違う
  • マスタデータ比較


方法4:COUNTIF で追加・削除を確認する

概要

「存在するかどうか」だけを確認する方法です

やり方
=IF(COUNTIF(before!A:A,A2)=0,"新規","既存")
向いているケース

  • 件数チェック
  • 追加・削除だけ確認したい場合


どの方法を選べばよいか?(初心者向け指針)

目的おすすめ方法
とにかく簡単にIF関数
見た目で確認条件付き書式
マスタ差分XLOOKUP
追加・削除確認COUNTIF

迷ったら、XLOOKUP が最も実務向き です


まとめ

Excel の差分抽出には、目的に応じてさまざまな方法があります

初心者の方はまず、

  • 行順が同じ → IF関数
  • 行順が違う → XLOOKUP
  • 確認だけ → 条件付き書式

この3つを押さえるだけで、多くの差分チェックに対応できます

「難しい方法を使うこと」よりも、目的に合った方法を選ぶことが、
正確な差分抽出への近道です


参考

Excel の差分抽出を行うツールを用意しておりますので、
是非お試しくださいませ ✨✨✨

https://yaonasu.blogspot.com/2025/11/ii-excel-diff.html
https://yaonasu.blogspot.com/2025/11/ii-exsh-diff.html


2025-12-29

openpyxl で 保存が重い、出来上がったファイルが大きすぎると感じたとき

実際の失敗談からの展開になります

openpyxl で作ったエクセルファイルがやけに大きい


あれれ、何かおかしいぞ?
前々から ii-win-merge は少し重たくて、ii-diff は軽い!!

そんな印象を持っていたんですが
100 を超えるファイルを比較したときに、顕著にその差が見て取れて

ついに「おかしい!」と確信する事態となりました!!


重たい!という症状は

PC 全体の動きがもっさりしだすし
タスクマネージャを見ると メモリはフルに・・・

HDD も 14GB くらいの余裕があったのに
数百MB まで落ちている

そして、最終的にエラーで結果の出力ができない!ときた・・・



絶対、どこかでメモリリークのような開放漏れがあるんだろうと思いました

そこからは いろいろと トライ&エラー です orz
1回のトライ(ここを変えたらどうなる?ってお試し)に 3~5H かかりました

なんせ
100 を超えるファイルを比較して、処理が終わるころにエラーするもんだから


いちいち時間がかかる
そして、その間、PC が重くなるから、何もできなくなります

難航しました・・・


原因がわかったのは
ファイル数を 50個くらいに抑えて出力した結果を ii-diff の結果と比較しているときでした


差分表の最後の行から Ctrl+下 でジャンプするファイルの最終行の位置が違う!!


そこに気づき着目しました!

ii-diff は 1,048,576行 (← 最新のエクセルで扱える最大行数)
ii-win-merge は 65,535行





行数が少ない ii-win-merge の方がファイルが大きくなるのはなぜ?と思う人もいるかもしれないですが・・・



ii-diff は値の入っている有効行が 差分表の最後の行(116行目)なのでエクセルの最終行に飛び
ii-win-merge は エクセルの最終行に飛ばないので、
差分表の後にも値の入っている行があって、その値の入っている最後の有効行に飛んだのだろう

そう解釈をしました (;^ω^)

よく見ると



実際
上図のようにグレー塗のセルが 65,535行まで続いていました


絶対これやん!!


そこを修正したら、さっくり軽くなり、約 7分 で結果出力できるようになりました ('ω')ノシ



シート当たりのデータ量が無駄に多かったんだもん
そら重いわな・・・


結論

openpyxl は ワークブックの save() で時間がかかります
保持していたデータを xml にして、エクセルのファイル構成を作って
zip に圧縮するらしいです

データ量に比例して時間が増えますので、
小さなデータを扱っているつもりなのに、とても時間がかかるときは

私のように
意図せず広い範囲のセルを使っていないか、ご確認くださいませ 🙇‍♂️🙇‍♂️🙇‍♂️







2025-12-26

相対パス指定のショートカットを作成する方法

 Windows でショートカットを作成すると絶対パスで本体を示すショートカットが作成されます ('ω')

 

会社生活を長くやっていると

 ・サーバーが変わりました

 ・旧サーバーから新サーバーでファイル・フォルダ構成そのままでコピーされる

ってことがときどき起こりえます


このとき、サーバーに置かれていたショートカットがリンク切れを起こして困ってしまいます

あらかじめ、絶対パスではない、相対パスのショートカットを配置しておけば、困ることもないのかな?と

 

相対パスでショートカットを作成できないかを調べてみた 口笛

 

ChatGPT 調べですが、Windows は標準では相対パスを推奨していないみたいで裏技的な技法らしいのですが、

リンクのプロパティからリンク先を以下のように指定したらよいらしいです ('ω')ノシ


%windir%\explorer.exe ..\ii-create-shortcut\icon.ico

 

実際、これをやろうとすると・・・ 以下のように、まぁまぁの手数が必要で かつ 相対パスを作り上げるのが面倒です

 

 1. ショートカットを作成する(本体ファイルを右クリック → ショートカットの作成) ※Win11 なら右クリックの後もう1手が必要

 2. ショートカットを適切なフォルダに移動させる

 3. 相対パスの文字列を作成する

 4. ショートカットのリンク先を変更する(ショートカットを右クリック → プロパティ → リンク先欄の修正)


ということで、

相対パス指定のショートカットを作成するアプリを作ってみました!! ('ω')ノシ


こちら になります

どうぞお試しくださいませ



ご訪問をありがとうございます ✨✨✨

八百茄子 は ソフトウェアエンジニア1名による小さな工房です 週末に スキルアップ と 八百茄子 向けのコンテンツ作成に勤しんでおります ご提供コンテンツ tools  にて 八百茄子 の作成したツールをご紹介しています knowhow  にて、 2x年の組込み系ソフトウェア開発...