SimpleTC キーワード集計
2025/02/14
入力したキーワードを含むログの実績時間を日別に集計
https://scrapbox.io/files/67af0be22c83970250c881d0.png
code:js
`dataviewjs
const startDate = moment().subtract(30, "days");
const endDate = moment();
let groupedData = {};
// 検索ボックスの作成
const container = dv.el("div", ""); // 結果を格納する親要素
const input = dv.el("input", "", { type: "text", placeholder: "検索キーワードを入力" });
input.style.marginBottom = "10px";
container.appendChild(input);
const resultDiv = dv.el("div", ""); // 検索結果の表示エリア
container.appendChild(resultDiv);
input.addEventListener("input", () => loadData(input.value.trim())); // 入力時に即適用
async function loadData(keyword = "") {
groupedData = {}; // データリセット
resultDiv.innerHTML = ""; // 古い結果を削除し、常に最新の1つだけ表示
let resultTitle = dv.el("h3", keyword ? 検索結果: "${keyword}" : "全データ表示");
resultDiv.appendChild(resultTitle);
for (let d = moment(startDate); d.isSameOrBefore(endDate); d.add(1, "day")) {
let dateStr = d.format("YYYY-MM-DD");
let dayOfWeek = d.format("ddd");
let filePath = notes/${dateStr}.md;
let fileContent = await dv.io.load(filePath).catch(() => null);
if (!fileContent) continue;
// キーワードがある場合、ファイル内に含まれていなければスキップ
if (keyword && !fileContent.includes(keyword)) continue;
for (let line of fileContent.split("\n")) {
if (keyword && !line.includes(keyword)) continue; // キーワードを含まない行はスキップ
let match = line.match(/(\d{2}:\d{2})-(\d{2}:\d{2})?\s*(?:\((\d+)\))?\s*(?:#(\w_\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}ー+)\s+)?(.+?)(?:\s+#(\w_\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}ー+))?(?:\s*\.*?\)?/u);
if (!match) continue;
let startTime = match1 ? moment(match1, "HH:mm") : null;
let endTime = match2 ? moment(match2, "HH:mm") : null;
let manualMinutes = match3 ? parseInt(match3, 10) : 0;
let duration = moment.duration(0);
if (startTime && endTime) {
duration = moment.duration(endTime.diff(startTime));
} else if (manualMinutes > 0) {
duration = moment.duration(manualMinutes, "minutes");
}
let dateKey = [[${dateStr}]] (${dayOfWeek});
if (!groupedDatadateKey) groupedDatadateKey = moment.duration(0);
groupedDatadateKey.add(duration);
}
}
updateTable();
}
function updateTable() {
let output = | 日付 (曜日) | 合計時間 |\n|------------|----------|\n;
let found = false;
for (let date of Object.keys(groupedData).sort().reverse()) {
let totalMinutes = groupedDatadate.asMinutes();
let formattedTime = Math.floor(totalMinutes / 60) + ":" + String(totalMinutes % 60).padStart(2, "0");
output += | ${date} | ${formattedTime} |\n;
found = true;
}
if (!found) output += "| 該当なし | -- |\n";
let tableElement = dv.el("pre", output); // すっきり表示
resultDiv.appendChild(tableElement);
}
// 初回ロード
loadData();
`