いま開発中のプログラムの進捗・・・
前回からCSVファイルの取込のコードを改良して確実に取り込めるようにして、AppSheetに引き渡せるように修正しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 |
// ✅ メニュー表示 =========================================================================== function onOpen() { const ui = SpreadsheetApp.getUi(); ui.createMenu('📋 データ転記メニュー') .addItem('🟢 CSVを取り込む', 'CSV_Import') .addItem('🟢 転記する', 'Transcription') .addItem("⬇ すべてのA列の最終行へ", "scrollToLastRowInColumnA_AllSheets_All") .addItem("📩 CSVメールを転送する", "forwardCSVEmailsOnce") .addSeparator() .addItem('🟢 列幅取得', 'getColumnWidths') .addItem('🟢 列幅設定', 'setColumnWidths') .addItem('🟢 文字置換', 'CharacterSubstitution') .addItem("👇 アクティブシートのA列の最終行へ", "scrollToLastRowInColumnA") .addSeparator() .addItem("❌ 特定スレッド非表示", "labelTargetThreads") // .addItem('🟢 サイドバーに曜日を表示", "showWeekdaySidebar') .addToUi(); } // ✅ CSVのImport =========================================================================== function CSV_Import() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const logSheet = ss.getSheetByName("取込log"); const query = 'subject:"[OMRON]測定結果" has:attachment -label:"古いOMRONデータ"'; const threads = GmailApp.search(query, 0, 50); if (!logSheet) { SpreadsheetApp.getUi().alert("❌ logシートが見つかりません"); return; } if (logSheet.getLastRow() > 1) { logSheet.getRange(2, 1, logSheet.getLastRow() - 1, logSheet.getMaxColumns()).clearContent(); } const headers = [["取込完了ログ", "tmp-body 午前 削除", "tmp-body 午後 削除", "tmp-blood 午前 削除", "tmp-blood 午後 削除", "tmp-activity 午前 削除", "tmp-activity 午後 削除"]]; logSheet.getRange(1, 1, 1, headers[0].length).setValues(headers).setBackgroundRGB(0, 112, 192) .setFontColor("white").setFontWeight("bold"); logSheet.setFrozenRows(1); logSheet.setColumnWidths(1, headers[0].length, 200); const results = { body: { am: [], pm: [], log: "", sheet: "tmp-body" }, blood: { am: [], pm: [], log: "", sheet: "tmp-blood" }, activity: { am: [], pm: [], log: "", sheet: "tmp-activity" } }; threads.forEach(thread => { thread.getMessages().forEach(message => { const subject = message.getSubject(); const sheetName = subject.includes("body") ? "tmp-body" : subject.includes("blood") ? "tmp-blood" : subject.includes("activity") ? "tmp-activity" : null; if (!sheetName) return; const sheet = ss.getSheetByName(sheetName); const attachments = message.getAttachments(); if (!sheet || attachments.length === 0) return; let csv = attachments[0].getDataAsString("UTF-8"); if (csv.includes("�") || csv.includes("謾") || csv.includes("諸")) { csv = attachments[0].getDataAsString("Shift_JIS"); } const csvData = Utilities.parseCsv(csv); if (csvData.length <= 1) return; if (sheet.getLastRow() > 1) { sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getMaxColumns()).clearContent(); } sheet.getRange(2, 1, csvData.length - 1, csvData[0].length).setValues(csvData.slice(1)); }); }); for (const type in results) { const sheet = ss.getSheetByName(results[type].sheet); if (!sheet) continue; const data = sheet.getDataRange().getValues(); const headers = data.shift(); const grouped = {}; data.forEach(row => { const date = new Date(row[0]); const key = Utilities.formatDate(date, "Asia/Tokyo", "yyyy-MM-dd") + (date.getHours() < 12 ? "_am" : "_pm"); if (!grouped[key]) grouped[key] = []; grouped[key].push(row); }); const filtered = [headers]; for (const key in grouped) { const group = grouped[key]; if (group.length > 1) { group.sort((a, b) => new Date(a[0]) - new Date(b[0])); const removed = group.slice(0, -1); filtered.push(group[group.length - 1]); removed.forEach(r => { const log = [`${Utilities.formatDate(new Date(r[0]), "Asia/Tokyo", "yyyy/MM/dd(E) H:mm:ss")} 削除`]; results[type][key.endsWith("_am") ? "am" : "pm"].push(log); }); } else { filtered.push(group[0]); } } sheet.clearContents(); sheet.getRange(1, 1, filtered.length, filtered[0].length).setValues(filtered); results[type].log = `${results[type].sheet} 取込完了 ${filtered.length - 1}件`; } // ログシート出力 logSheet.insertRows(2); logSheet.getRange("A2").setValue(results.body.log); logSheet.getRange("A3").setValue(results.blood.log); logSheet.getRange("A4").setValue(results.activity.log); logSheet.getRange(2, 2, results.body.am.length || 1, 1).setValues(results.body.am.length ? results.body.am : [["該当なし"]]); logSheet.getRange(2, 3, results.body.pm.length || 1, 1).setValues(results.body.pm.length ? results.body.pm : [["該当なし"]]); logSheet.getRange(2, 4, results.blood.am.length || 1, 1).setValues(results.blood.am.length ? results.blood.am : [["該当なし"]]); logSheet.getRange(2, 5, results.blood.pm.length || 1, 1).setValues(results.blood.pm.length ? results.blood.pm : [["該当なし"]]); logSheet.getRange(2, 6, results.activity.am.length || 1, 1).setValues(results.activity.am.length ? results.activity.am : [["該当なし"]]); logSheet.getRange(2, 7, results.activity.pm.length || 1, 1).setValues(results.activity.pm.length ? results.activity.pm : [["該当なし"]]); } // ✅ TMPからlogシートへ転記 =========================================================================== // ✅ tmp-body シートの E1〜R列のデータを log シートの I1〜V列へ転記 ================================ function Transcription() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const sourceSheet = ss.getSheetByName("tmp-body"); const targetSheet = ss.getSheetByName("log"); if (!sourceSheet || !targetSheet) { SpreadsheetApp.getUi().alert("❌ tmp-body または log シートが見つかりません。"); return; } const lastRow = sourceSheet.getLastRow(); if (lastRow < 2) { SpreadsheetApp.getUi().alert("❗ 転記するデータが存在しません。"); return; } const numRows = lastRow - 1; // ▼ A列・C列・D列のデータ取得 const colA = sourceSheet.getRange(2, 1, numRows, 1).getValues(); // A列 = 測定日 const colC = sourceSheet.getRange(2, 3, numRows, 1).getValues(); // C列 = 体重 const colD = sourceSheet.getRange(2, 4, numRows, 1).getValues(); // D列 = 体脂肪% // ▼ logシートの A, B, D列 に転記 for (let i = 0; i < numRows; i++) { targetSheet.getRange(i + 2, 1).setValue(colA[i][0]); // A列 targetSheet.getRange(i + 2, 2).setValue(colC[i][0]); // B列 targetSheet.getRange(i + 2, 4).setValue(colD[i][0]); // D列 } // ▼ E1〜R1 の表題、E2〜R(最終行) のデータ取得 const headerValues = sourceSheet.getRange(1, 5, 1, 14).getValues(); // E1:R1 const bodyValues = sourceSheet.getRange(2, 5, numRows, 14).getValues(); // E2:R const allValues = [...headerValues, ...bodyValues]; // ▼ logシートの I〜V列に転記 targetSheet.getRange(1, 9, allValues.length, 14).setValues(allValues); // ▼ A列〜V列(1行目)の装飾 const headerRange = targetSheet.getRange(1, 1, 1, 22); headerRange .setBackgroundRGB(66, 133, 244) .setFontColor("white") .setFontWeight("bold") .setHorizontalAlignment("center") .setVerticalAlignment("middle"); // ▼ A列〜V列(2行目以降)の中央揃え const dataRange = targetSheet.getRange(2, 1, numRows, 22); dataRange .setHorizontalAlignment("center") .setVerticalAlignment("middle"); // ▼ 1行目固定 targetSheet.setFrozenRows(1); // ▼ A1〜V(最終行) に罫線を設定 const borderRange = targetSheet.getRange(1, 1, allValues.length, 22); borderRange.setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID); } // ✅ セル選択時に曜日をポップアップ表示する処理 ================================================================= function onSelectionChange(e) { const sheet = e.range.getSheet(); // 選択したシート const cell = e.range; // 選択範囲 // 対象シート名の確認(シート名が異なる場合は修正) if (sheet.getName() !== "log") return; // A列以外を無視 if (cell.getColumn() !== 1) return; const value = cell.getValue(); // セルの値を取得 // 値が日付でなければ終了 if (!(value instanceof Date)) return; // 曜日を取得 const days = ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日']; const weekday = days[value.getDay()]; // カレンダーのみ表示 SpreadsheetApp.getUi().showSidebar(html); // メッセージボックスで表示 // SpreadsheetApp.getUi().alert(`📅 選択された日付「${value.toLocaleString()}」は「${weekday}」です`); } // ======================================================================== // // ✅ サイドバーに曜日を表示する処理 // function showWeekdaySidebar() { // const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // const cell = sheet.getActiveCell(); // const value = cell.getValue(); // // セルの値が日付でない場合は中止 // if (!(value instanceof Date)) { // SpreadsheetApp.getUi().alert("❌ 選択したセルには日付が含まれていません。"); // return; // } // // 曜日を取得 // const weekdays = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"]; // const weekday = weekdays[value.getDay()]; // // HTMLを生成(曜日のみ表示) // const html = HtmlService.createHtmlOutput(` // <div style="font-family:sans-serif;padding:20px;"> // <h2 style="color:#4285f4;">📅 曜日</h2> // <p style="font-size:24px;"><strong>${weekday}</strong></p> // </div> // `).setTitle("曜日表示"); // // サイドバーに表示 // SpreadsheetApp.getUi().showSidebar(html); // } // ======================================================================== // ✅ アクティブシートのA列の最終行に正確にスクロールする処理 function scrollToLastRowInColumnA() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); const columnA = sheet.getRange("A:A").getValues(); // A列すべて取得 let lastRow = 0; // 下から上に向かって最初に値がある行を見つける for (let i = columnA.length - 1; i >= 0; i--) { if (columnA[i][0] !== "") { lastRow = i + 1; // 配列は0始まりなので+1 break; } } if (lastRow > 1) { sheet.setActiveRange(sheet.getRange("A" + lastRow)); } else { SpreadsheetApp.getUi().alert("A列にデータが見つかりません。"); } } // ✅ すべてのシートのA列の最終行に正確にスクロールする処理 function scrollToLastRowInColumnA_AllSheets_All() { const sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets(); let noDataSheets = []; // データが見つからないシート名を格納 for (const sheet of sheets) { const columnA = sheet.getRange("A:A").getValues(); let lastRow = 0; // A列を下から上へ検索して最終行を特定 for (let i = columnA.length - 1; i >= 0; i--) { if (columnA[i][0] !== "") { lastRow = i + 1; break; } } if (lastRow > 1) { SpreadsheetApp.setActiveSheet(sheet); // シートをアクティブに sheet.setActiveRange(sheet.getRange("A" + lastRow)); // 最終行を選択 } else { noDataSheets.push(sheet.getName()); } } // すべてのシートの処理が終了した後、必要があればアラート表示 if (noDataSheets.length === sheets.length) { SpreadsheetApp.getUi().alert("すべてのシートのA列にデータが見つかりません。"); } else if (noDataSheets.length > 0) { SpreadsheetApp.getUi().alert("以下のシートではA列にデータが見つかりませんでした:\n" + noDataSheets.join(", ")); } } // ======================================================================== // ✅ 改良済みコード(3ファイルを1通にまとめて送信) function forwardCSVEmailsOnce() { const searchQuery = 'subject:"[OMRON]測定結果" newer_than:7d has:attachment'; const recipient = "YOUR_EMAIL@example.com"; // ← 公開用にダミーアドレスへ変更 // 一意の件名を作成(日時付き) const now = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyyMMdd_HHmm"); const newSubject = "一括CSV転送_" + now; const threads = GmailApp.search(searchQuery); if (threads.length === 0) { Logger.log("🔍 該当するスレッドが見つかりません。"); return; } let allAttachments = []; let foundCount = 0; for (const thread of threads) { const messages = thread.getMessages(); for (const msg of messages) { try { const attachments = msg.getAttachments(); if (attachments.length > 0) { for (const file of attachments) { // ファイル名が指定ワードを含む場合のみ追加 const name = file.getName(); if ( name.includes("BodyComposition") || name.includes("BloodPressure") || name.includes("Activity") ) { allAttachments.push(file); Logger.log(`📎 追加: ${name}`); foundCount++; } } } } catch (e) { Logger.log(`❌ 添付ファイル取得エラー: ${e.message}`); } } } if (allAttachments.length === 0) { Logger.log("⚠️ 添付ファイルが見つかりませんでした。"); return; } // 転送メールの送信 GmailApp.sendEmail(recipient, newSubject, "3種類のCSVファイルが一括送付されました。", { attachments: allAttachments }); Logger.log(`✅ 転送完了:${foundCount} 件の添付ファイルを送信しました。`); } // ✅ 特定スレッド非表示 =========================================================================== function labelTargetThreads() { const labelName = "非表示対象"; // 付けたいラベル名 const label = GmailApp.createLabel(labelName); // 存在しなければ作成 // 件名に一致するスレッドを検索 const query = 'subject:"[OMRON]測定結果" OR subject:"主要3CSVダウンロード" OR subject:"があなたと共有されました"' const threads = GmailApp.search(query, 0, 50); // 最大50件 if (threads.length === 0) { Logger.log("❌ 該当するスレッドが見つかりませんでした。"); return; } // ラベルを付与 threads.forEach(thread => { thread.addLabel(label); }); Logger.log(`✅ ${threads.length} 件のスレッドに「${labelName}」ラベルを付けました。`); } // ✅ 文字の置換 =========================================================================== function CharacterSubstitution() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("log"); if (!sheet) { Logger.log("❌ シート「log」が見つかりません。"); return; } // A1セルのチェックと変換("測定日" → 日付) let a1Value = sheet.getRange("A1").getValue().toString().trim(); a1Value = a1Value.replace(/^"|"$/g, ""); // 両端の " を除去 Logger.log("🔍 A1セルの実際の値: [" + a1Value + "]"); if (a1Value === "測定日") { sheet.getRange("A1").setValue("日付"); Logger.log("✅ A1セルを「日付」に変換しました。"); } else { Logger.log("⚠️ A1セルは『測定日』と一致しませんでした。"); } // B1セルのチェックと変換(体重(kg) → 体重) let b1Value = sheet.getRange("B1").getValue().toString().trim(); b1Value = b1Value.replace(/^"|"$/g, ""); // 万一"が含まれている場合に備える Logger.log("🔍 B1セルの実際の値: [" + b1Value + "]"); if (b1Value === "体重(kg)") { sheet.getRange("B1").setValue("体重"); Logger.log("✅ B1セルを「体重」に変換しました。"); } else { Logger.log("⚠️ B1セルは『体重(kg)』と一致しませんでした。"); } } // ✅ 列幅を取得 =========================================================================== function getColumnWidths() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // アクティブなシートを取得 const lastColumn = sheet.getLastColumn(); // データがある最後の列番号を取得 let widths = []; for (let col = 1; col <= lastColumn; col++) { const width = sheet.getColumnWidth(col); widths.push(`列${col}: 幅=${width}px`); } Logger.log("列幅一覧:\n" + widths.join("\n")); } // ✅ 指定された列幅を設定する (シート名:log)=============================== function setColumnWidths() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // 指定された列幅の配列(1列目から順) const widths = [ 133,70,180,70, 70,100,100,100, 85,100,95,68, 85,134,134,134,94, 148,148,148,33,69 ]; // 配列の内容に従って列幅を設定 for (let col = 0; col < widths.length; col++) { sheet.setColumnWidth(col + 1, widths[col]); // 列番号は1から始まる } } // ✅✅✅ 図形とテキストボックスで作成する「擬似フローチャート」(シート名:フロー)=========================== function drawCompleteFlowchart() { formatFlowSheet(); // セル幅や行高など整える drawFlowchartInSheet(); // フローチャート描画 } // ✅ シートのフォーマット(列幅・行高・セル結合など) function formatFlowSheet() { const ss = SpreadsheetApp.getActiveSpreadsheet(); let sheet = ss.getSheetByName("フロー"); if (!sheet) { sheet = ss.insertSheet("フロー"); } else { sheet.clear(); } // 必要な範囲を仮に初期化して列と行を確保 sheet.getRange("A1:J15").setValue(""); // 列幅設定 const setWidths = { "A": 30, "B": 30, "C": 30, "D": 30, "E": 30, "F": 30, "G": 180, "H": 30, "I": 30, "J": 30 }; for (const col in setWidths) { const colNum = sheet.getRange(col + "1").getColumn(); sheet.setColumnWidth(colNum, setWidths[col]); } // 行の高さ設定 const rowHeights = { 1: 20, 3: 20, 5: 20, 7: 20, 8: 40, 9: 20, 10: 20, 11: 20, 12: 40, 13: 20, 14: 20 }; for (const row in rowHeights) { sheet.setRowHeight(Number(row), rowHeights[row]); } // セル結合 sheet.getRange("G10:G11").merge(); sheet.getRange("B12:E12").merge(); sheet.getRange("G13:G14").merge(); // 罫線の設定 // 下罫線:D10:F10, D13:F13, H10, H13 sheet.getRange("D10:F10").setBorder(false, false, true, false, false, false); sheet.getRange("D13:F13").setBorder(false, false, true, false, false, false); sheet.getRange("H10").setBorder(false, false, true, false, false, false); sheet.getRange("H13").setBorder(false, false, true, false, false, false); // 左罫線:D11, D13, H11:H13 sheet.getRange("D11").setBorder(false, false, false, true, false, false); sheet.getRange("D13").setBorder(false, false, false, true, false, false); sheet.getRange("H11:H13").setBorder(false, false, false, true, false, false); // 強制的に罫線を引く //const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("フロー"); // H10 に下罫線 const h10 = sheet.getRange("H10"); h10.setValue(" ") // 半角スペースを入れる(必要に応じて削除可) .setBorder(false, false, true, false, false, false, "#000000", SpreadsheetApp.BorderStyle.SOLID); // H14 に上罫線 const h14 = sheet.getRange("H14"); h14.setValue(" ") // 半角スペースを入れる .setBorder(true, false, false, false, false, false, "#000000", SpreadsheetApp.BorderStyle.SOLID); } // ✅ 擬似フローチャートを描画 function drawFlowchartInSheet() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("フロー"); const texts = [ { cell: "G2", value: "CSV_Import()" }, { cell: "G4", value: "メールメッセージを取得" }, { cell: "G6", value: "添付ファイルを取得" }, { cell: "G8", value: "CSVデータを転記" }, { cell: "G10", value: "重複データの判定" }, { cell: "B12", value: "重複行の削除" }, { cell: "G13", value: "終了" } ]; texts.forEach(t => { const range = sheet.getRange(t.cell); range.setValue(t.value); range.setHorizontalAlignment("center").setVerticalAlignment("middle"); range.setBorder(true, true, true, true, true, true); range.setFontWeight("bold"); range.setFontSize(12); sheet.setRowHeight(range.getRow(), 40); // 列が B列(列番号2)の場合だけ30px、それ以外は180px const colNum = range.getColumn(); sheet.setColumnWidth(colNum, colNum === 2 ? 30 : 180); }); // 矢印を文字で表現 sheet.getRange("G3").setValue("↓").setHorizontalAlignment("center"); sheet.getRange("G5").setValue("↓").setHorizontalAlignment("center"); sheet.getRange("G7").setValue("↓").setHorizontalAlignment("center"); sheet.getRange("G9").setValue("↓").setHorizontalAlignment("center"); sheet.getRange("G11").setValue("↓").setHorizontalAlignment("center"); sheet.getRange("C11").setValue("はい").setHorizontalAlignment("center").setVerticalAlignment("middle"); sheet.getRange("I12").setValue("い\nい\nえ").setWrap(true); sheet.getRange("G13").setValue("終了").setHorizontalAlignment("center"); } |
上記のGASコードでオムロン社製の血圧計や体重計、活動計などが収集したデータをカンマ形式のCSVデータをGasScriptでスプレットシートに取り込む処理は完成した。
様々な人が使う前提で数多くシーンを想定し、エラー対策も万全を期すように設計したつもりです。
オムロンアプリをユーザーがスマホから目で確認したりCSVを加工して、いちから下記のような表を作成するには時間的なコストが負担になります。
上記のコードは時間的なコストを節約するためGASスクリプトをコツコツと作成していました。
下記の画像見てもわかるように7つのシートに取り込んだメールの添付ファイルから各シートに流し込み、最終的に log というシートに転記するようにしました。
目的のアプリはこの log シートをもとにいろいろと展開させていきたいと考えてます。

現在、稼働中(まだ、完璧な完成ではないが・・・)です。




また、将来的なアプリ無料配布に備えて、Google Work Space にサブスク契約しました。
Google Work Space のサブスクについて(メリット)は、後ほど解説する予定です。
今回の投稿はここまで・・・次回はもっともっと操作のしやすいようにする過程を記す予定です。
投稿者プロフィール

-
asamai-cts Owner
あさまいCTSの代表オヤジです(2024年現在=63歳)
横手市中央町で「ラーメン与市」を2012年まで約15年間を経営。
その後、「横手市雇用創出協議会 実践支援員」を経て、一時会社勤めをするが再度、自営業の世界に戻る。
現在の「あさまいCTS」は2019年1月に起業。業務内容は主に、パソコンの修理、出張スマホ・パソコン教室、ホームページ作成 その他 何でも屋みたいなものです・・・
最新の投稿
未分類2025年6月4日Gメールをもっと便利に
未分類2025年4月6日Webで稼働するシステムを製作中(1)
未分類2025年6月4日Webで稼働するシステムを製作中(2)
未分類2025年4月5日心不全手帳を作りました