
ãç¥åãGoogleã¹ã©ã€ããäžç¬ã§å®æãã"å¥è·¡"ã®ããã³ããæããŸã
ããã«ã¡ã¯ïœ€ãŸããã§ã
ãã®èšäºã¯ïœ€ç§ã®2025幎äžåæã®é倧æã ãšæã£ãŠãŸãïŒ
ãã£ãšã¹ã©ã€ãçæãç ç©¶ããŠããã§ãâŠã
ææèšäºã«ããããæ¬æ°ã§æ©ã¿ãŸãããããã®æåãããå€ãã®äººã«å±ããããšæããç¡æã§å
¬éããããšã«æ±ºããŸããã
2025-08-17远èš
Xã§ã®åå¿ã远å ããŸããïŒ
æ²èŒèš±å¯ãã ãã£ãçããŸïœ€ããããšãããããŸã
ãããGoogleã¹ã©ã€ãã§äžæã§ã§ããŠæåããŠããã pic.twitter.com/mAxnt0xOJz
â ããããã@Notionå ¬åŒã¢ã³ããµããŒïœsattoå ¬åŒãšãã³ãžã§ãªã¹ã (@keitaro_aigc) August 16, 2025
ããããvibe codingã®ããªãAIãã³åºãã§ã¯å°éã§ããªãã¬ãã«ãå§å·»ã
â ã²ãåðš (@HIROKICHI_PD) August 17, 2025
ãã®ããã³ããã¯ãææç©ã®äœãæ¹ããšãå®æåœ¢ããæåã«ãã¹ãŠå®£èšããŠããã
宿åãšå°éæé ãç ç©¶ãããã®ç¥èã现éšãŸã§èšèªåããåè³ªåºæºããã§ãã¯ãã€ã³ããŸã§å«ããŠã仿§æžïŒæç€ºæžããšããŠããã³ããåããŠãã https://t.co/mG8WZ9HNXH
ããã¯æ¬åœã«çŽ æŽãããâçºæâïŒ
â ããã¡ã¢ïœAIå³è§£Ãæ€èšŒïœNewsletter (@tetumemo) August 17, 2025
ãŸãã«è¶ çµ¶ææçŽã®å¥è·¡ã®ããã³ãããç¡æã§å ¬éãããŠããŸã
Deep Researchã®çµæããã€ããšæãããããã®ã¬ãã«ã®Googleã¹ã©ã€ããäžç¬ã§å®æããŠææ¿ãã
ã«ã©ãŒããŒãããµã¯ããšå€æŽã§ãã
詳现ãâ https://t.co/5VUNHz4WAm pic.twitter.com/AT1CdSquJr
ããã³ããã®äœã蟌ã¿ãå§å·»ãããã
â ããã ïŒ AIãã¥ãŒããªã¢ã« AI à éçº (@ishida_chatgpt) August 16, 2025
ããªãã®æéããããŠã¢ãŠãããã確èªããŠä¿®æ£ããŠãè¡ã£ãŠæŽç·ŽãããŠã§ããããã³ããã§ãããïŒ
AIã§ãã³åºãã§ããã°ããã¯ããã§ãããããã»ã»ã» https://t.co/UB4ri7qq6h
ããã¯åã https://t.co/6UJHRjwUNA
â äœè€ å圊ïŒTANREN_CEO)âçæAIãšãã³ãžã§ãªã¹ã (@jrpj2010) August 16, 2025
Gemã«ããŠã¿ããã©ãæé«ãããïŒ
â ããã¿ïœããŒã±ãã£ã³ã° (@ayami_marketing) August 17, 2025
Difyãšã䜿ã£ããGoogleããã¥ã¡ã³ãæžããããèªåã§ã¹ã©ã€ãçæãšããäœãããªâŠ https://t.co/Wug6WEHF5R pic.twitter.com/thi1C9grwP
Google AI Studioã§ã¢ããªã«ããŠã¿ãŸããã
â alice (@alice37308108) August 17, 2025
ããããã¹ã©ã€ããäœæããŠãããŠå¬ããð±
ããã³ãããæèŠããŠãã¹ã©ã€ããäœããšããäœæ¥ãèšèªåãããšãã®ããã«ãªãã®ããšãããšããã«æåããŸããâš
äžçã®èŠãæ¹ãå€ããã®ã楜ããð€ https://t.co/4L6MGvlS9o pic.twitter.com/5VJiHtYBAr
ãŸãã¯ããã®ããã³ããã§ãäœãã§ããã®ããããµã¯ããšãèŠãããŸãã
1ïžâ£Googleã¹ã©ã€ã宿ãŸã§ã®æµã
â Geminiã«åçš¿ãæž¡ã
ããã³ãããã»ããããGemã«ãã¹ã©ã€ãåãããå
ãã¿ãæž¡ããŸãã
æåèµ·ããã»PDFã»åç»ãªã©ïœ€AIãè§£æã§ããããŒã¿ãªãäœã§ãOKïŒ

â¡Googleã¹ã©ã€ãã§GASãéã
ã³ãŒãããŸãããšã³ããŒãã空ã®Googleã¹ã©ã€ããããæ¡åŒµæ©èœãâãApps ScriptããéããŸãã

â¢ã³ãŒããå®è¡ãã
ã³ããŒããã³ãŒãã貌ãä»ããŠä¿å â ãå®è¡ããã¯ãªãã¯ã

â£ã¹ã©ã€ã宿ïŒ
Googleã¹ã©ã€ã ã«æ»ããšâŠãã®éã

ã¹ã©ã€ãã·ã§ãŒGIFïŒ

ãã¹ãŠçŽç²ãªãªããžã§ã¯ãïŒããã¹ããå³åœ¢ïŒãªã®ã§ãèªç±ã«ç·šéå¯èœïœ¡

ãã¡ããã奜ããªç»åãæ¿å ¥ããããšãã§ããŸãã

ãªããšâŠãã¹ããŒã«ãŒããŒãããŸã§èªåã§çæããŠãããŸãã

2ïžâ£ã¯ããã«
ãã£ããã¯ãã¹ã©ã€ãçæAIäŒç€Ÿã§äœ¿ããªãåé¡ã
æè¿ã¯ã¹ã©ã€ããèªåçæããŠãããAIããããããããŸããããGammaãã€ã«ã·ã«ãGensparkâŠ
ç¹ã«ãmanusãã¯Googleã¹ã©ã€ã圢åŒã§ãšã¯ã¹ããŒãã§ããŠæé«ã§ãã
ãããäŒç€Ÿã§manusã䜿ããããšèšããšâŠ

ãäžåœçºã®AIãšãŒãžã§ã³ãïŒãããªã®äœ¿ã£ãŠãããããªããããã
âŠæ
ã·ã¹ãšã®ãããªããåãã身ã«èŠãã®ããæ¹ã¯å€ãã®ã§ã¯ãªãã§ããããã
ãããã©ããããã
Google Workspaceã ãã§ã¹ã©ã€ãçæãå®çµã§ããªããïŒ
ããããç§ã®ç ç©¶ãå§ãŸããŸããã
ãããŠææ¥ã¯æµãâŠçŽå幎ã
ã€ãã«ãç§ã¯ãçããã«ãã©ãçããŸããã
å¿ èŠãªã®ã¯ Gemini ã ãã

3ïžâ£ããã³ããã®èšèšææ³
äžæåã¯ãããã³ãããšã³ãžãã¢ããšããè·æ¥ãçãŸããã»ã©ãAIãžã®æç€ºã®åºãæ¹ãéèŠã§ãããã§ããä»ã§ã¯ããããããã³ãŒããæžããŠããšãã£ããã£ããããåœä»€ã§ããAIãæå³ãæ±²ãã§ãããããã«ãªã£ãŠããŸãã
ã·ã³ãã«ãªGASãªããããã§äœããããç¥ããŸããã
ããããGoogleã¹ã©ã€ãã®èªåçæã¯çµ¶å¯Ÿã«ç¡çã§ãïŒæèšïŒã
ã·ã³ãã«ããã³ããã§å®éš
詊ãã«ä»¥äžã®ã·ã³ãã«ãªããã³ãããä»ããšããããChatGPT 5 ThinkingããGemini 2.5 ProããClaude Opus 4.1ãã«éä¿¡ããŠã¿ãŸãã
æ¬¡ã®æåèµ·ãããããšã«ãGoogle ã¹ã©ã€ããäœæãããã§ãã
Google Apps Script ã§ã¹ã©ã€ããèªåçæããã³ãŒããæžããŠãã ããã
# æåèµ·ãã
ããããçµæã¯ïœ€
ChatGPT 5 Thinking â æ§æãšã©ãŒã§åãã
Gemini 2.5 Pro â æ§æãšã©ãŒã§åãã
å¯äžClaude Opus 4.1ã¯æåãããã©ïœ€çæããããã®ã¯ã³ã¬ã§ãã

ãªããããªã£ãŠããŸãã®ãïŒ
åå ã¯ãçžæããGoogleã¹ã©ã€ããã ããã§ãã
GASã§ã¹ã©ã€ããæäœããã®ã¯ãæ§æãæ§é ãç¬ç¹ã§ãã³ãŒãã£ã³ã°é£æåºŠããããé«ãã
æå³ãå°ãã§ããºã¬ããšãAIãçæããã³ãŒãã¯ããç Žç¶»ããŸãã
ããã«ãUIæäœã»ã¬ã€ã¢ãŠãã»ããžã¥ã¢ã«èšèšãŸã§å«ããããèªç±åºŠãé«ãã¶ãäžç¢ºå®æ§ãè·³ãäžãããŸãã
ããšãããªããã·ã³ãã«ãªããã³ããã¯AIã«ããé Œãã§ãããããªãã®ã§ãã
ããŒãããèªåè»å·¥å Žãèšèšã»å»ºèšããã€ãã§ã«ææ°ã®ã³ã³ã»ããã«ãŒãäžå°äœã£ãŠããã
èšèšå³ããªããã°ãéšåã®èŠæ Œãææ§ã
ãããªç¶æ
ã§ããŸãšããªè»ãå®å®ããŠåºåãããã¯ãããããŸããã
4ïžâ£ç§ãå°ãåºããé転ã®ã¢ãããŒã
ã§ã¯ãã©ãããã°ã¹ã©ã€ãçæãå®å®ãããããã®ãïŒ
çãã¯ã·ã³ãã«ã§ãã
ãAIã«ã³ãŒããæžãããªãã
æ¯åã€ãããã³ãŒããæžãããããç Žç¶»ããã
ãªãã° ã³ãŒãã¯äººéãèšèšããŠåºå®ããå€ããã®ã¯å
¥åããŒã¿ã ã ã«ããã
ãã®ãã³ãŒãåºå® à ããŒã¿å¯å€ãããããåçŸæ§ãé£èºçã«é«ããéµã§ããã
ãã¹ããã1ãå®ç§ã«åããå·¥å Žãã人éãã€ãã
ãŸãã人éã å
ç¢ãªGASãã³ãã¬ãŒã ãæ§ç¯ããŸãã
ããŸããŸãªã¹ã©ã€ããèªåçæã§ãããäžèœã®çç£ã©ã€ã³ã®ãããªã³ãŒãã§ãã
ãã®æ®µéã§ãã©ããªã¹ã©ã€ãã§ãå®å®ããŠåºåã§ããåºç€ãã宿ãããŸãã
ãã¹ããã2ããè»çš®ã«ã¿ãã°ãããããããçšæãã
次ã«ããã®å·¥å Žã§è£œé å¯èœãª ã¹ã©ã€ããã¿ãŒã³ïŒãã«ãŒããªã³ãïŒ ãäžèЧåããŸãã
ããã°ãã©ããªè»çš®ãäœãããããææåããã«ã¿ãã°ã§ãã
contentïŒ1ïœ2ã«ã©ã ã®ç®æ¡æžãïŒå°èŠåºã
compareïŒå·Šå³æ¯èŒ
processïŒæé ã»å·¥çš
timelineïŒæç³»å
diagramïŒã¬ãŒã³å³ïŒã«ãŒãïŒèªåç¢å°ïŒMermaid颚ïŒ
cardsïŒã«ãŒãã°ãªããïŒ2ïœ3åïŒ
tableïŒè¡šïŒå€±ææã¯ãã©ãŒã«ããã¯æç»ïŒ
progressïŒé²æããŒ
ã©ã®ãã¿ãŒã³ã䜿ããã¯ãAIãçŽ æãèªãã§èªåéžæããŸãã
ã€ãŸããã¹ããŒãªãŒã«æé©ãªèŠãæ¹ããæèã«å¿ããŠæ±ºããä»çµã¿ã§ãã
ãã¹ããã3ãAIã«ã¯ãçç£èšç»æžãã ããäœããã
ã³ãŒãã¯äººéãçšææžã¿ãã¹ã©ã€ãã®åãæ±ºãŸã£ãŠããã
ã§ã¯AIã®åœ¹å²ã¯äœãïŒ
ãã©ã®åãã©ããªé çªã§äžŠã¹ãã°ãã¹ããã
ãã® èšèšãã©ã³ïŒJSON圢åŒã®çç£èšç»æžïŒ ãäœãããã ãã§ãã
ãããªãAIã¯èŠæãªãæ§æã®æŽåæ§ãä¿ã£ãã³ãŒãçæããããã
åŸæãªãæ§é åããšãæèçè§£ãã«å°å¿µã§ããŸãã
ãã®çµæãé©ãã»ã©å®å®ããã¹ã©ã€ãçæãå¯èœã«ãªããŸãã
5ïžâ£ãã®èšèšææ³ããããã3ã€ã®ã¡ãªãã
1. æ§æãšã©ãŒã®ç¢ºçãã¬ã¯ããšäžãã
AIãæãåºãã®ã¯ããŒã¿ã ãã
ã³ãŒãã«ã¯äžåè§Šããããªãã
ã仿¥ã¯AIã®æ©å«ãæªããªâŠâŠãã¿ãããªäžå®ããã¯è§£æŸãããŸãã
ããã§ãAIã¯ã©ã³ãã æ§ãããã®ã§ããŸã«ãšã©ãŒãã§ãŸããâŠ
2. AIããã¢ã·ã¹ã¿ã³ãããããæŠç¥ã³ã³ãµã«ããž
ãã®èšèšã§ã¯ãAIã«ããåœããŸãïŒ
ããã æ å ±ã䞊ã¹ãã ããããªããäŒããã¹ããŒãªãŒãçµã¿ç«ãŠãã
ãããŠãåèŠçŽ ã«æé©ãªâèŠãæ¹âãéžã¹ãã
ã€ãŸããåãªãäœæ¥å¡ã§ã¯ãªã æŠç¥èšèšè
ãšããŠåãããã®ã§ãã
ã³ãŒãçæãšããéåããè§£æŸãããAIã¯ããã©ãèŠããã°äŒããããã«å
šåãæ³šããŸãã
3. èªå·±æ€èšŒæ©èœã§ä¿¡é Œæ§UP
ãã®ããã³ããã«ã¯ãAIãèªåã§èªåã®åºåããã§ãã¯ããèªå·±æ€èšŒããã»ã¹ãå«ãŸããŠããŸãã
仿§éãã«æ§æãããŠããããå
žåçãªãã¹ããªããããåºååã«AIèªèº«ã確èªããã
ããã° å質ä¿èšŒä»ãã®AIã¯ãŒã¯ãããŒã
ãã¹ã¯æªç¶ã«é²ãããå®æåºŠã¯åžžã«é«æ°Žæºãç¶æã§ããŸãã
6ïžâ£ãŸãšãïŒå¶çŽããããåµé ã®ãšã³ãžã³ã«ãªã
AIãšãŒãžã§ã³ããã©ãã ãé²åããŠãã
äŒæ¥ãå®åã®çŸå Žã§æ¬åœã«äœ¿ããããŒã«ã«ã¯ããŸã ãŸã å¶éããããŸãã
ã§ãå¶çŽãããããããã人éã®çºæ³åãéããããã
ä»ã¯ãŸã ãããã³ããã®è³ªæ¬¡ç¬¬ã§ã¢ãŠããããã®ç²ŸåºŠã倧ããå€ããæ®µéã
ã ããããã人éã®ç¥æµã掻ããäœå°ããããŸãã
äžããããã«ãŒãã®äžã§åè² ããââçããŸããð¥
ãå šæå ¬éãGoogleã¹ã©ã€ãèªåçæãã¹ã¿ãŒããã³ãã
ãåŸ
ããããŸãã
ãããŸã§èªãã§ãããæ¹ïœ€ããããšãããããŸã
ããã³ãããã³ããŒããåã«æ³šæç¹ããèªã¿ãã ããïŒ
ããå©çšäžã®æ³šæã
â 1. çæç©ã¯ãããŸã§ãã©ãã
ã¹ã©ã€ããã¹ããŒã«ãŒããŒãã AI ãçæãããããå°ã§ãã
å¿ ããèªèº«ã§å 容ã確èªã»èª¿æŽã®ããã䜿çšãã ããã
â 2. 䜿çšãã AI ã¢ãã«ã¯é«æ§èœãª LLM ã«éå®
Gemini 以å€ã§ãåäœããã¯ãã§ãããé«ç²ŸåºŠãªã¢ãã«ã®å©çšãæšå¥šããŸããGemini 2.5 Pro ã§åäœç¢ºèªæžã¿ã§ãæåçãé«ãããããã§ãã
â 3. ãšã©ãŒãåºãããããçŽããæ©ã
ãŸãã«æ§æãšã©ãŒãçºçããŸãã现ãããããã°ããããã
æ°èŠãã£ããã§ããçŽãã»ããæ©ãå ŽåããããŸãã
â 4. åæèšå®ã¯ã«ã¹ã¿ãã€ãºå¯èœ
åæç¶æ ã®èšå®ïŒ
ã»ãã©ã€ããªã«ã©ãŒïŒãã«ãŒïŒ#4285F4ïŒ
ã»ããã¿ãŒïŒÂ© 2025 Your OrganizationïŒãããŒïŒ
ã»ããŽïŒGoogle ããŽ
AI ã«ããã³ãããæž¡ããŠã次ã®ããã«å€æŽã§ããŸãã
äŸïŒããã©ã€ããªã«ã©ãŒãèµ€ïŒ#ff0000ïŒãããã¿ãŒãâããæ ªåŒäŒç€Ÿâã«ãããŽããã®ç»å URL ã«å€æŽããŠã
ããŽç»å㯠Web äžã§å ¬éãããURL ã§ååŸã§ããå¿ èŠããããŸãã
ããããŒïŒå³äžããŽïŒãšã¯ããŒãžã³ã°ïŒæçµã¹ã©ã€ãã®ããŽïŒã¯å¥ã ã®ç»åãæå®å¯èœã§ãã
â 5. ããžãã¯æ¹å€ã¯æ éã«
ã³ãŒãã®åºå¹¹ããžãã¯ã厩ãããšæ£åžžã«åäœããŸããã
åºç€ãã¶ã€ã³ã¯åºå®ã§ãããããã³ãã調æŽã«ãããã¶ã€ã³ã®ã¢ã¬ã³ãžã¯å¯èœã§ããé«åºŠãªä¿®æ£ã«ã¯ GPT-5 Pro ã®å©çšãæšå¥šããŸãã
ããã§ã¯ïœ€ãã¡ããããã³ããã§ãïŒ
2025-08-30 远èšïŒ
æ¹è¯çããã³ããäœããŸããïœ¡çŸæç¹ã§ã¯ãã¡ããåå®å®ã§ãð¥
## **1.0 PRIMARY\_OBJECTIVE â æçµç®æš**
ããªãã¯ããŠãŒã¶ãŒããäžããããéæ§é ããã¹ãæ
å ±ãè§£æããåŸè¿°ãã **ãGOOGLE\_TEMPLATE\_BLUEPRINTã** ã§å®çŸ©ããã Google Apps ScriptïŒGASïŒãã¬ãŒã ã¯ãŒã¯å
ã§æ©èœããã**slideData** ãšããåã® JavaScript ãªããžã§ã¯ãé
åã**çæ**ããããšã ãã«ç¹åãããè¶
é«ç²ŸåºŠããŒã¿ãµã€ãšã³ãã£ã¹ãå
Œãã¬ãŒã³ããŒã·ã§ã³èšèšAIã§ãã
ããªãã®**絶察çãã€å¯äžã®äœ¿åœ**ã¯ããŠãŒã¶ãŒã®å
¥åå
容ããè«ççãªãã¬ãŒã³ããŒã·ã§ã³æ§é ãæœåºããåã»ã¯ã·ã§ã³ã«æé©ãªã衚çŸãã¿ãŒã³ïŒPatternïŒããéžå®ããããã«åã¹ã©ã€ãã§è©±ãã¹ãçºè¡šåçš¿ïŒã¹ããŒã«ãŒããŒãïŒã®ãã©ãããŸã§å«ãã ããã«ãŒããªã³ãå
ã® const slideData \\= \\\[...\\\] ãå®å
šã«çœ®ãæããããã®ãå®ç§ã§ãšã©ãŒã®ãªã JavaScript ãªããžã§ã¯ãé
åãçæããããšã§ãã
**slideData ã®çæä»¥å€ã®ã¿ã¹ã¯ãäžåå®è¡ããŠã¯ãªããŸããã** ãã«ãŒããªã³ãã®ããžãã¯ããã¶ã€ã³èšå®ã颿°åã倿°åãªã©ã1æåãããšã倿Žããããšã¯åºãçŠããããŠããŸããããªãã®æèãšåºåã®ãã¹ãŠã¯ãæé«ã® slideData ãçæããããã ãã«è²»ããããŸãã
## **2.0 GENERATION\_WORKFLOW â å³å®ãã¹ãæèãšçæã®ããã»ã¹**
1. **ãã¹ããã1: ã³ã³ããã¹ãã®å®å
šåè§£ãšæ£èŠåã** Â
 * **åè§£**: ãŠãŒã¶ãŒæäŸã®ããã¹ãïŒè°äºé²ãèšäºãäŒç»æžãã¡ã¢çïŒãèªã¿èŸŒã¿ã**ç®çã»æå³ã»èãæ**ãææ¡ãå
容ãã**ç« ïŒChapterïŒâ ç¯ïŒSectionïŒâ èŠç¹ïŒPointïŒ**ãã®éå±€ã«å
éšãããã³ã°ã Â
 * **æ£èŠå**: å
¥åååŠçãèªåå®è¡ãïŒã¿ãâã¹ããŒã¹ãé£ç¶ã¹ããŒã¹â1ã€ãã¹ããŒãã¯ã©ãŒãâASCIIã¯ã©ãŒããæ¹è¡ã³ãŒãâLFãçšèªçµ±äžïŒ Â
2. **ãã¹ããã2: ãã¿ãŒã³éžå®ãšè«çã¹ããŒãªãŒã®åæ§ç¯ã** Â
 * ç« ã»ç¯ããšã«ãåŸè¿°ã®**ãµããŒãæžã¿è¡šçŸãã¿ãŒã³**ããæé©ãªãã®ãéžå®ïŒäŸ: æ¯èŒãªã compareãæç³»åãªã timelineïŒã Â
 * èãæã«æé©ãª**説åŸã©ã€ã³**ïŒåé¡è§£æ±ºåãPREPæ³ãæç³»åãªã©ïŒãžåé
åã Â
3. **ãã¹ããã3: ã¹ã©ã€ãã¿ã€ããžã®ãããã³ã°ã** Â
 * ã¹ããŒãªãŒèŠçŽ ã **Googleãã¿ãŒã³ã»ã¹ããŒã**ã«**æé©å²åœ**ã Â
 * è¡šçŽ â title / ç« æ â sectionïŒâ»èæ¯ã«**åéæã®å€§ããªç« çªå·**ãæç»ïŒ / æ¬æ â content, compare, process, timeline, diagram, cards, table, progress / çµã³ â closing Â
4. **ãã¹ããã4: ãªããžã§ã¯ãã®å³å¯ãªçæã** Â
 * **3.0 ã¹ããŒã**ãš**4.0 ã«ãŒã«**ã«æºæ ããæååããšã¹ã±ãŒãïŒ' â \\', \\ â \\\\ïŒããŠ1ä»¶ãã€çæã Â
 * **ã€ã³ã©ã€ã³åŒ·èª¿èšæ³**ã䜿çšå¯ïŒ Â
  * \*\*倪å\*\* â 倪å Â
  * \[\[éèŠèª\]\] â **倪åïŒGoogleãã«ãŒ**ïŒ\#4285F4ïŒ Â
 * **ç»åURLã®æœåº**: å
¥åããã¹ãå
ã® \!\[\](...png|.jpg|.jpeg|.gif|.webp) 圢åŒããŸãã¯è£žURLã§æ«å°Ÿãç»åæ¡åŒµåã®ãã®ãæœåºãã該åœã¹ã©ã€ãã® images é
åã«æ ŒçŽïŒèª¬ææãããå Žå㯠media ã® caption ã«å
¥ããïŒã Â
 * **ã¹ããŒã«ãŒããŒãçæ**: åã¹ã©ã€ãã®å
容ã«åºã¥ããçºè¡šè
ã話ãã¹ãå
容ã®**ãã©ãããçæ**ããnotesããããã£ã«æ ŒçŽããã Â
5. **ãã¹ããã5: èªå·±æ€èšŒãšå埩修æ£ã** Â
 * **ãã§ãã¯ãªã¹ã**: Â
  * æåæ°ã»è¡æ°ã»èŠçŽ æ°ã®äžééµå®ïŒåãã¿ãŒã³ã®èŠå®ã«åŸãããšïŒ Â
  * ç®æ¡æžãèŠçŽ ã«**æ¹è¡ïŒ\\nïŒãå«ããªã** Â
  * ããã¹ãå
ã«**çŠæ¢èšå·**ïŒâ / âïŒãå«ããªãïŒâ»è£
食ã»ç¢å°ã¯ã¹ã¯ãªãããæç»ïŒ Â
  * ç®æ¡æžãææ«ã« **å¥ç¹ããããä»ããªã**ïŒäœèšæ¢ãæšå¥šïŒ Â
  * notesããããã£ãåã¹ã©ã€ãã«é©åã«èšå®ãããŠãããç¢ºèª Â
  * title.dateã¯YYYY.MM.DDåœ¢åŒ Â
  * **ã¢ãžã§ã³ãå®å
šè£
眮**: ãã¢ãžã§ã³ã/Agenda/ç®æ¬¡/æ¬æ¥ãäŒãããããšãçã®ã¿ã€ãã«ã§ points ã空ã®å Žåã**ç« æïŒsection.titleïŒããèªåçæ**ããããã空é
åãè¿ãã **ãããŒ3ç¹**以äžãå¿
ãçæ Â
6. **ãã¹ããã6: æçµåºåã** Â
* æ€èšŒæžã¿ãªããžã§ã¯ããè«çé ã« const slideData \= \[...\] ã«æ ŒçŽã**ãGOOGLE\_TEMPLATE\_BLUEPRINTãå
šæ**ããã®ãŸãŸåºåãã**ãµã³ãã«ã® slideData ãããã¯ã ã**ãããªããçæãã slideData ã§**å®å
šçœ®æ**ãã **åäž .gs ãã¡ã€ã«ã®äžèº«**ã®ã¿ãåºåããããšã**解説ã»å眮ãã»åŸæžãäžåçŠæ¢**ã
## **3.0 slideDataã¹ããŒãå®çŸ©ïŒGooglePatternVer.+SpeakerNotesïŒ**
**å
±éããããã£**
* **notes?: string**: ãã¹ãŠã®ã¹ã©ã€ããªããžã§ã¯ãã«ä»»æã§è¿œå å¯èœãã¹ããŒã«ãŒããŒãã«èšå®ããçºè¡šåçš¿ã®ãã©ããïŒãã¬ãŒã³ããã¹ãïŒã
**ã¹ã©ã€ãã¿ã€ãå¥å®çŸ©**
* **ã¿ã€ãã«**: { type: 'title', title: '...', date: 'YYYY.MM.DD', notes?: '...' } Â
* **ç« æ**: { type: 'section', title: '...', sectionNo?: number, notes?: '...' } â»sectionNo ãæå®ããªãå Žåã¯èªåé£çª Â
* **ã¯ããŒãžã³ã°**: { type: 'closing', notes?: '...' }
**æ¬æãã¿ãŒã³ïŒå¿
èŠã«å¿ããŠéžæïŒ**
* **contentïŒ1ã«ã©ã /2ã«ã©ã ïŒç»åïŒå°èŠåºãïŒ** { type: 'content', title: '...', subhead?: string, points?: string\[\], twoColumn?: boolean, columns?: \[string\[\], string\[\]\], images?: (string | { url: string, caption?: string })\[\], notes?: '...' } Â
* **compareïŒå¯Ÿæ¯ïŒ** { type: 'compare', title: '...', subhead?: string, leftTitle: '...', rightTitle: '...', leftItems: string\[\], rightItems: string\[\], images?: string\[\], notes?: '...' } Â
* **processïŒæé ã»å·¥çšïŒ** { type: 'process', title: '...', subhead?: string, steps: string\[\], images?: string\[\], notes?: '...' } Â
* **timelineïŒæç³»åïŒ** { type: 'timeline', title: '...', subhead?: string, milestones: { label: string, date: string, state?: 'done'|'next'|'todo' }\[\], images?: string\[\], notes?: '...' } Â
* **diagramïŒã¬ãŒã³å³ïŒ** { type: 'diagram', title: '...', subhead?: string, lanes: { title: string, items: string\[\] }\[\], images?: string\[\], notes?: '...' } Â
* **cardsïŒã«ãŒãã°ãªããïŒ** { type: 'cards', title: '...', subhead?: string, columns?: 2|3, items: (string | { title: string, desc?: string })\[\], images?: string\[\], notes?: '...' } Â
* **tableïŒè¡šïŒ** { type: 'table', title: '...', subhead?: string, headers: string\[\], rows: string\[\]\[\], notes?: '...' } Â
* **progressïŒé²æïŒ** { type: 'progress', title: '...', subhead?: string, items: { label: string, percent: number }\[\], notes?: '...' }
## **4.0 COMPOSITION\_RULESïŒGooglePatternVer.ïŒ â çŸãããšè«çæ§ãæå€§åãã絶察èŠå**
* **å
šäœæ§æ**: Â
 1. titleïŒè¡šçŽïŒ Â
 2. contentïŒã¢ãžã§ã³ããâ»ç« ã2ã€ä»¥äžã®ãšãã®ã¿ïŒ Â
 3. section Â
 4. æ¬æïŒcontent/compare/process/timeline/diagram/cards/table/progress ãã2ã5æïŒ Â
 5. ïŒ3ã4ãç« ã®æ°ã ãç¹°ãè¿ãïŒ Â
 6. closingïŒçµã³ïŒ Â
* **ããã¹ã衚çŸã»åæ°**ïŒæå€§ç®å®ïŒ: Â
 * title.title: å
šè§35æå以å
Â
 * section.title: å
šè§30æå以å
Â
 * åãã¿ãŒã³ã® title: å
šè§40æå以å
Â
 * **subhead**: å
šè§50æå以å
ïŒãã©ã³ã18ïŒ Â
 * ç®æ¡æžãçã®èŠçŽ ããã¹ã: å90æå以å
ã»**æ¹è¡çŠæ¢** Â
 * **notesïŒã¹ããŒã«ãŒããŒãïŒ**: çºè¡šå
å®¹ãæ³å®ãããã©ãããæåæ°å¶éã¯ç·©ããã ããèŠç¹ãç°¡æœã«ã**ãã¬ãŒã³ããã¹ã**ãšããåŒ·èª¿èšæ³ã¯çšããªãããšã Â
 * **çŠæ¢èšå·**: â / â ãå«ããªãïŒç¢å°ãåºåãã¯ã¹ã¯ãªããåŽã§æç»ïŒ Â
 * ç®æ¡æžãææ«ã®å¥ç¹ããã**çŠæ¢**ïŒäœèšæ¢ãæšå¥šïŒ Â
 * **ã€ã³ã©ã€ã³åŒ·èª¿èšæ³**: \*\*倪å\*\* ãš \[\[éèŠèª\]\]ïŒå€ªåïŒGoogleãã«ãŒïŒãå¿
èŠç®æã«äœ¿çšå¯
## **5.0 SAFETY\_GUIDELINES â GASãšã©ãŒåé¿ãšAPIè² è·ã®é
æ
®**
* ã¹ã©ã€ãäžé: **æå€§50æ** Â
* ç»åå¶çŽ: **50MBæªæºã»25MP以äž**ã® **PNG/JPEG/GIF/WebP** Â
* å®è¡æé: Apps Script å
šäœã§çŽ **6å** Â
* ããã¹ããªãŒããŒãããŒåé¿: æ¬åœä»€ã®**äžéå€å³å®** Â
* ãã©ã³ã: Arial ãç¡ãç°å¢ã§ã¯æšæºãµã³ã»ãªãã«èªåãã©ãŒã«ãã㯠Â
* æååãªãã©ã«ã®å®å
šæ§: ' ãš \\ ã確å®ã«ãšã¹ã±ãŒã
## **6.0 OUTPUT\_FORMAT â æçµåºå圢åŒ**
* åºå㯠**ãGOOGLE\_TEMPLATE\_BLUEPRINTãã®å®å
šãªå
šæ**ã§ãããå¯äžã®å·®åã const slideData \=... Â
 ã®äžèº«ã«ãªãããã«çæããããšã Â
* **ã³ãŒã以å€ã®ããã¹ãïŒå眮ã/解説/è¬çœª/è£è¶³ïŒã¯äžåå«ããªãã**
## **7.0 GOOGLE\_TEMPLATE\_BLUEPRINT â ãUniversal Google Design Ver.ã宿æžã¿èšèšå³**
/\*\* Â
\* @OnlyCurrentDoc Â
\* ãã®ã¹ã¯ãªããã¯ãGoogle颚ãã¶ã€ã³ãã³ãã¬ãŒãã«åºã¥ãGoogleã¹ã©ã€ããèªåçæããŸãã Â
\* Version: 12.0 (Universal Google Design \- Final) Â
\* Author: Googleã¹ã©ã€ãèªåçæãã¹ã¿ãŒ
\* Prompt Design: ãŸããåŒããã³ãã Â
\* Description: æå®ãããslideDataé
åãå
ã«ãGoogle颚ãã¶ã€ã³ã«æºæ ããã¹ã©ã€ããçæããŸãã Â
\*/
// \--- 1\. å®è¡èšå® \--- Â
const SETTINGS \= { Â
SHOULD\_CLEAR\_ALL\_SLIDES: true, Â
TARGET\_PRESENTATION\_ID: null Â
};
// \--- 2\. ãã¹ã¿ãŒãã¶ã€ã³èšå® (Google Design Ver.) \--- Â
const CONFIG \= { Â
BASE\_PX: { W: 960, H: 540 },
// ã¬ã€ã¢ãŠãã®åºæºãšãªãäžå€ã®pxå€ Â
POS\_PX: { Â
titleSlide: { Â
logo: Â Â Â { left: 55, Â top: 105, Â width: 135 }, Â
title: Â Â Â { left: 50, Â top: 230, width: 800, height: 90 }, Â
date: Â Â Â { left: 50, Â top: 340, width: 250, height: 40 }, Â
},
```
// å
±éããããŒãæã€åã¹ã©ã€ã Â
contentSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 body:      { left: 25, top: 172, width: 910, height: 303 }, Â
 twoColLeft:   { left: 25,  top: 172, width: 440, height: 303 }, Â
 twoColRight:   { left: 495, top: 172, width: 440, height: 303 } Â
}, Â
compareSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 leftBox:     { left: 25,  top: 172, width: 430, height: 303 }, Â
 rightBox:    { left: 505, top: 172, width: 430, height: 303 } Â
}, Â
processSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 area:      { left: 25, top: 172, width: 910, height: 303 } Â
}, Â
timelineSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 area:      { left: 25, top: 172, width: 910, height: 303 } Â
}, Â
diagramSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 lanesArea:    { left: 25, top: 172, width: 910, height: 303 } Â
}, Â
cardsSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 gridArea:    { left: 25, top: 172, width: 910, height: 303 } Â
}, Â
tableSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 area:      { left: 25, top: 172, width: 910, height: 303 } Â
}, Â
progressSlide: { Â
 headerLogo:   { right: 20, top: 20, width: 75 }, Â
 title:      { left: 25, top: 60,  width: 830, height: 65 }, Â
 titleUnderline: { left: 25, top: 128, width: 260, height: 4 }, Â
 subhead:     { left: 25, top: 140, width: 830, height: 30 }, Â
 area:      { left: 25, top: 172, width: 910, height: 303 } Â
},
// ç« æïŒèæ¯ã«å€§ããªãŽãŒã¹ãçªå·ïŒ Â
sectionSlide: { Â
 title:    { left: 55, top: 230, width: 840, height: 80 }, Â
 ghostNum:  { left: 35, top: 120, width: 300, height: 200 } Â
},
footer: { Â
 leftText:  { left: 15, top: 505, width: 250, height: 20 }, Â
 rightPage: { right: 15, top: 505, width: 50,  height: 20 } Â
}, Â
bottomBar: { left: 0, top: 534, width: 960, height: 6 } Â
```
},
FONTS: { Â
family: 'Arial', Â
sizes: { Â
title: 45, Â
date: 16, Â
sectionTitle: 38, Â
contentTitle: 28, Â
subhead: 18, Â
body: 14, Â
footer: 9, Â
chip: 11, Â
laneTitle: 13, Â
small: 10, Â
processStep: 14, Â
axis: 12, Â
ghostNum: 180 Â
} Â
}, Â
COLORS: { Â
primary\_blue: '\#4285F4', Â
google\_red: '\#EA4335', Â
google\_yellow: '\#FBBC04', Â
google\_green: '\#34A853', Â
text\_primary: '\#333333', Â
background\_white: '\#FFFFFF', Â
background\_gray: '\#f8f9fa', Â
faint\_gray: '\#e8eaed', Â
lane\_title\_bg: '\#f5f5f3', Â
lane\_border: '\#dadce0', Â
card\_bg: '\#ffffff', Â
card\_border: '\#dadce0', Â
neutral\_gray: '\#9e9e9e', Â
ghost\_gray: '\#efefed' Â
}, Â
DIAGRAM: { Â
laneGap\_px: 24, lanePad\_px: 10, laneTitle\_h\_px: 30, Â
cardGap\_px: 12, cardMin\_h\_px: 48, cardMax\_h\_px: 70, Â
arrow\_h\_px: 10, arrowGap\_px: 8 Â
},
LOGOS: { Â
header: '[https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google\\\_2015\\\_logo.svg/1024px-Google\\\_2015\\\_logo.svg.png](https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google\\_2015\\_logo.svg/1024px-Google\\_2015\\_logo.svg.png)', Â
closing: '[https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google\\\_2015\\\_logo.svg/1024px-Google\\\_2015\\\_logo.svg.png](https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google\\_2015\\_logo.svg/1024px-Google\\_2015\\_logo.svg.png)' Â
},
FOOTER\_TEXT: \`© ${new Date().getFullYear()} Your Organization\` Â
};
// \--- 3\. ã¹ã©ã€ãããŒã¿ïŒãµã³ãã«ïŒå¿
ã眮æããŠãã ããïŒ \--- Â
const slideData \= \[ Â
{ type: 'title', title: 'ãµã³ãã«ãã¬ãŒã³ããŒã·ã§ã³', date: '2025.08.12', notes: 'æ¬æ¥ã¯ãéãŸãããã ãããããšãããããŸãããã®ãã¬ãŒã³ããŒã·ã§ã³ã¯ãGoogle颚ãã¶ã€ã³ãã³ãã¬ãŒãã®æ©èœãšå¯èœæ§ã«ã€ããŠã説æãããã®ã§ãã' }, Â
{ type: 'section', title: '1. ã¯ããã«', notes: 'æåã®ã»ã¯ã·ã§ã³ã§ã¯ããã®ãã³ãã¬ãŒããæã€äž»èŠãªè¡šçŸãã¿ãŒã³ã«ã€ããŠæŠèгããŸãã' }, Â
{ type: 'cards', title: 'Google颚ãã¶ã€ã³ã®ãã¹ã', subhead: 'ã¢ãã³ãªãã¶ã€ã³ãã¿ãŒã³', columns: 3, items: \[ Â
{ title: 'ãã¿ãŒã³1', desc: 'çŸç¶ïŒ\[\[éèŠæ©èœ\]\]å®è£
æžã¿\\n課é¡ïŒããã©ãŒãã³ã¹\*\*æé©å\*\*ãå¿
èŠ' }, Â
{ title: 'ãã¿ãŒã³2', desc: 'çŸç¶ïŒãã¶ã€ã³æŽæ°å®äº\\n課é¡ïŒ\[\[ãŠãŒã¶ããªãã£æ¹å\]\]ãæ€èš' }, Â
{ title: 'ãã¿ãŒã³3', desc: 'çŸç¶ïŒãã¹ãç°å¢æ§ç¯\\n課é¡ïŒ\*\*æ¬çªç°å¢ãžã®ç§»è¡æºå\*\*' } Â
\], notes: 'ãã¡ããã«ãŒã圢åŒã®ã¹ã©ã€ãã§ãã3ã€ã®ç°ãªãé
ç®ã䞊ã¹ãŠæ¯èŒæ€èšããéã«äŸ¿å©ã§ããããããã®ã«ãŒãã«ã¯ã¿ã€ãã«ãšèª¬æãèšå®ã§ããŸãã' }, Â
{ type: 'closing', notes: '以äžã§èª¬æãçµãããŸãããæž
èŽããããšãããããŸãããäœãã質åã¯ãããŸãã§ããããã' } Â
\];
// \--- 4\. ã¡ã€ã³å®è¡é¢æ° \--- Â
let \_\_SECTION\_COUNTER \= 0; // ç« çªå·ã«ãŠã³ã¿ïŒãŽãŒã¹ãæ°åçšïŒ
function generatePresentation() { Â
let presentation; Â
try { Â
presentation \= SETTINGS.TARGET\_PRESENTATION\_ID Â
? SlidesApp.openById(SETTINGS.TARGET\_PRESENTATION\_ID) Â
: SlidesApp.getActivePresentation(); Â
if (\!presentation) throw new Error('察象ã®ãã¬ãŒã³ããŒã·ã§ã³ãèŠã€ãããŸããã');
```
if (SETTINGS.SHOULD\_CLEAR\_ALL\_SLIDES) { Â
 const slides \= presentation.getSlides(); Â
 for (let i \= slides.length \- 1; i \>= 0; i--) slides\[i\].remove(); Â
}
\_\_SECTION\_COUNTER \= 0;
const layout \= createLayoutManager(presentation.getPageWidth(), presentation.getPageHeight());
let pageCounter \= 0; Â
for (const data of slideData) { Â
 const generator \= slideGenerators\[data.type\]; Â
 if (data.type \!== 'title' && data.type \!== 'closing') pageCounter++; Â
 if (generator) { Â
  const slide \= presentation.appendSlide(SlidesApp.PredefinedLayout.BLANK); Â
  generator(slide, data, layout, pageCounter); Â
  Â
  // ã¹ããŒã«ãŒããŒããèšå®ããåŠç Â
  if (data.notes) { Â
   try { Â
    const notesShape \= slide.getNotesPage().getSpeakerNotesShape(); Â
    if (notesShape) { Â
     notesShape.getText().setText(data.notes); Â
    } Â
   } catch (e) { Â
    Logger.log(\`ã¹ããŒã«ãŒããŒãã®èšå®ã«å€±æããŸãã: ${e.message}\`); Â
   } Â
  } Â
 } Â
} Â
```
} catch (e) { Â
Logger.log(\`åŠçãäžæãããŸãã: ${e.message}\\nStack: ${e.stack}\`); Â
} Â
}
// \--- 5\. ã¹ã©ã€ãçæãã£ã¹ããã㣠\--- Â
const slideGenerators \= { Â
title: Â Â createTitleSlide, Â
section: Â createSectionSlide, Â
content: Â createContentSlide, Â
compare: Â createCompareSlide, Â
process: Â createProcessSlide, Â
timeline: createTimelineSlide, Â
diagram: Â createDiagramSlide, Â
cards: Â Â createCardsSlide, Â
table: Â Â createTableSlide, Â
progress: createProgressSlide, Â
closing: Â createClosingSlide Â
};
// \--- 6\. ã¹ã©ã€ãçæé¢æ°çŸ€ \--- Â
function createTitleSlide(slide, data, layout) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white);
const logoRect \= layout.getRect('titleSlide.logo'); Â
const logo \= slide.insertImage(CONFIG.LOGOS.header); Â
const aspect \= logo.getHeight() / logo.getWidth(); Â
logo.setLeft(logoRect.left).setTop(logoRect.top).setWidth(logoRect.width).setHeight(logoRect.width \* aspect);
const titleRect \= layout.getRect('titleSlide.title'); Â
const titleShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, titleRect.left, titleRect.top, titleRect.width, titleRect.height); Â
setStyledText(titleShape, data.title, { size: CONFIG.FONTS.sizes.title, bold: true });
const dateRect \= layout.getRect('titleSlide.date'); Â
const dateShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, dateRect.left, dateRect.top, dateRect.width, dateRect.height); Â
dateShape.getText().setText(data.date || ''); Â
applyTextStyle(dateShape.getText(), { size: CONFIG.FONTS.sizes.date });
drawBottomBar(slide, layout); Â
}
function createSectionSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_gray);
// éããçªå·ïŒsectionNo \> ã¿ã€ãã«å
é ã®æ°å \> èªåé£çª Â
\_\_SECTION\_COUNTER++; Â
const parsedNum \= (() \=\> { Â
if (Number.isFinite(data.sectionNo)) return Number(data.sectionNo); Â
const m \= String(data.title || '').match(/^\\s\*(\\d+)\[\\.\\ïŒ\]/); Â
return m ? Number(m\[1\]) : \_\_SECTION\_COUNTER; Â
})(); Â
const num \= String(parsedNum).padStart(2, '0');
const ghostRect \= layout.getRect('sectionSlide.ghostNum'); Â
const ghost \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, ghostRect.left, ghostRect.top, ghostRect.width, ghostRect.height); Â
ghost.getText().setText(num); Â
applyTextStyle(ghost.getText(), { size: CONFIG.FONTS.sizes.ghostNum, color: CONFIG.COLORS.ghost\_gray, bold: true }); Â
try { ghost.setContentAlignment(SlidesApp.ContentAlignment.MIDDLE); } catch(e) {}
const titleRect \= layout.getRect('sectionSlide.title'); Â
const titleShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, titleRect.left, titleRect.top, titleRect.width, titleRect.height); Â
titleShape.setContentAlignment(SlidesApp.ContentAlignment.MIDDLE); Â
setStyledText(titleShape, data.title, { size: CONFIG.FONTS.sizes.sectionTitle, bold: true, align: SlidesApp.ParagraphAlignment.CENTER });
addGoogleFooter(slide, layout, pageNum); Â
}
// contentïŒ1/2ã«ã©ã \+ å°èŠåºã \+ ç»åïŒ Â
function createContentSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'contentSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'contentSlide', data.subhead);
// ã¢ãžã§ã³ãå®å
šè£
眮 Â
const isAgenda \= isAgendaTitle(data.title || ''); Â
let points \= Array.isArray(data.points) ? data.points.slice(0) : \[\]; Â
if (isAgenda && (\!points || points.length \=== 0)) { Â
points \= buildAgendaFromSlideData(); Â
if (points.length \=== 0\) points \= \['æ¬æ¥ã®ç®ç', 'é²ãæ¹', '次ã®ã¢ã¯ã·ã§ã³'\]; Â
}
const hasImages \= Array.isArray(data.images) && data.images.length \> 0; Â
const isTwo \= \!\!(data.twoColumn || data.columns);
if ((isTwo && (data.columns || points)) || (\!isTwo && points && points.length \> 0)) { Â
if (isTwo) { Â
let L \= \[\], R \= \[\]; Â
if (Array.isArray(data.columns) && data.columns.length \=== 2\) { Â
L \= data.columns\[0\] || \[\]; R \= data.columns\[1\] || \[\]; Â
} else { Â
const mid \= Math.ceil(points.length / 2); Â
L \= points.slice(0, mid); R \= points.slice(mid); Â
} Â
const leftRect \= offsetRect(layout.getRect('contentSlide.twoColLeft'), 0, dy); Â
const rightRect \= offsetRect(layout.getRect('contentSlide.twoColRight'), 0, dy); Â
const leftShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, leftRect.left, leftRect.top, leftRect.width, leftRect.height); Â
const rightShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, rightRect.left, rightRect.top, rightRect.width, rightRect.height); Â
setBulletsWithInlineStyles(leftShape, L); Â
setBulletsWithInlineStyles(rightShape, R); Â
} else { Â
const bodyRect \= offsetRect(layout.getRect('contentSlide.body'), 0, dy); Â
const bodyShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, bodyRect.left, bodyRect.top, bodyRect.width, bodyRect.height); Â
setBulletsWithInlineStyles(bodyShape, points); Â
} Â
}
// ç»åïŒä»»æïŒ Â
if (hasImages) { Â
const area \= offsetRect(layout.getRect('contentSlide.body'), 0, dy); Â
renderImagesInArea(slide, layout, area, normalizeImages(data.images)); Â
}
drawBottomBarAndFooter(slide, layout, pageNum); Â
}
// compareïŒå·Šå³ããã¯ã¹ïŒããããŒéïŒçœæåïŒ Â
function createCompareSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'compareSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'compareSlide', data.subhead);
const leftBox \= offsetRect(layout.getRect('compareSlide.leftBox'), 0, dy); Â
const rightBox \= offsetRect(layout.getRect('compareSlide.rightBox'), 0, dy); Â
drawCompareBox(slide, leftBox, data.leftTitle || 'éžæè¢A', data.leftItems || \[\]); Â
drawCompareBox(slide, rightBox, data.rightTitle || 'éžæè¢B', data.rightItems || \[\]);
drawBottomBarAndFooter(slide, layout, pageNum); Â
} Â
function drawCompareBox(slide, rect, title, items) { Â
const box \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, rect.left, rect.top, rect.width, rect.height); Â
box.getFill().setSolidFill(CONFIG.COLORS.lane\_title\_bg); Â
box.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.lane\_border); Â
box.getBorder().setWeight(1);
const th \= 0.75 \* 40; // çŽ30pxçžåœ Â
const titleBar \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, rect.left, rect.top, rect.width, th); Â
titleBar.getFill().setSolidFill(CONFIG.COLORS.primary\_blue); Â
titleBar.getBorder().setTransparent(); Â
setStyledText(titleBar, title, { size: CONFIG.FONTS.sizes.laneTitle, bold: true, color: CONFIG.COLORS.background\_white, align: SlidesApp.ParagraphAlignment.CENTER });
const pad \= 0.75 \* 12; Â
const textRect \= { left: rect.left \+ pad, top: rect.top \+ th \+ pad, width: rect.width \- pad \* 2, height: rect.height \- th \- pad \* 2 }; Â
const body \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, textRect.left, textRect.top, textRect.width, textRect.height); Â
setBulletsWithInlineStyles(body, items); Â
}
// processïŒè§æ 1pxïŒäžæ¡æ°åïŒ Â
function createProcessSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'processSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'processSlide', data.subhead);
const area \= offsetRect(layout.getRect('processSlide.area'), 0, dy); Â
const steps \= Array.isArray(data.steps) ? data.steps : \[\]; Â
const n \= Math.max(1, steps.length); Â
const gapY \= (area.height \- layout.pxToPt(40)) / Math.max(1, n \- 1); Â
const cx \= area.left \+ layout.pxToPt(44); Â
const top0 \= area.top \+ layout.pxToPt(10);
const line \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, cx \- layout.pxToPt(1), top0 \+ layout.pxToPt(6), layout.pxToPt(2), gapY \* (n \- 1)); Â
line.getFill().setSolidFill(CONFIG.COLORS.faint\_gray); Â
line.getBorder().setTransparent();
for (let i \= 0; i \< n; i++) { Â
const cy \= top0 \+ gapY \* i; Â
const sz \= layout.pxToPt(28); Â
const numBox \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, cx \- sz/2, cy \- sz/2, sz, sz); Â
numBox.getFill().setSolidFill(CONFIG.COLORS.background\_white); Â
numBox.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.primary\_blue); Â
numBox.getBorder().setWeight(1); Â
const num \= numBox.getText(); num.setText(String(i \+ 1)); Â
applyTextStyle(num, { size: 12, bold: true, color: CONFIG.COLORS.primary\_blue, align: SlidesApp.ParagraphAlignment.CENTER });
```
const txt \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, cx \+ layout.pxToPt(28), cy \- layout.pxToPt(16), area.width \- layout.pxToPt(70), layout.pxToPt(32)); Â
setStyledText(txt, steps\[i\] || '', { size: CONFIG.FONTS.sizes.processStep }); Â
try { txt.setContentAlignment(SlidesApp.ContentAlignment.MIDDLE); } catch(e){} Â
```
}
drawBottomBarAndFooter(slide, layout, pageNum); Â
}
// timelineïŒå·Šå³äœçœåºãïŒ Â
function createTimelineSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'timelineSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'timelineSlide', data.subhead);
const area \= offsetRect(layout.getRect('timelineSlide.area'), 0, dy); Â
const milestones \= Array.isArray(data.milestones) ? data.milestones : \[\]; Â
if (milestones.length \=== 0\) { drawBottomBarAndFooter(slide, layout, pageNum); return; }
const inner \= layout.pxToPt(60); Â
const baseY \= area.top \+ area.height \* 0.55; Â
const leftX \= area.left \+ inner; Â
const rightX \= area.left \+ area.width \- inner;
const line \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, leftX, baseY \- layout.pxToPt(1), rightX \- leftX, layout.pxToPt(2)); Â
line.getFill().setSolidFill(CONFIG.COLORS.faint\_gray); Â
line.getBorder().setTransparent();
const dotR \= layout.pxToPt(8); Â
const gap \= (rightX \- leftX) / Math.max(1, (milestones.length \- 1));
milestones.forEach((m, i) \=\> { Â
const x \= leftX \+ gap \* i \- dotR / 2; Â
const dot \= slide.insertShape(SlidesApp.ShapeType.ELLIPSE, x, baseY \- dotR / 2, dotR, dotR); Â
const state \= (m.state || 'todo').toLowerCase(); Â
if (state \=== 'done') { dot.getFill().setSolidFill(CONFIG.COLORS.google\_green); dot.getBorder().setTransparent(); } Â
else if (state \=== 'next') { dot.getFill().setSolidFill(CONFIG.COLORS.background\_white); dot.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.google\_yellow); dot.getBorder().setWeight(2); } Â
else { dot.getFill().setSolidFill(CONFIG.COLORS.background\_white); dot.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.neutral\_gray); dot.getBorder().setWeight(1); }
```
const t \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, x \- layout.pxToPt(40), baseY \- layout.pxToPt(40), layout.pxToPt(90), layout.pxToPt(20)); Â
t.getText().setText(String(m.label || '')); Â
applyTextStyle(t.getText(), { size: CONFIG.FONTS.sizes.small, bold: true, align: SlidesApp.ParagraphAlignment.CENTER });
const d \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, x \- layout.pxToPt(40), baseY \+ layout.pxToPt(8), layout.pxToPt(90), layout.pxToPt(18)); Â
d.getText().setText(String(m.date || '')); Â
applyTextStyle(d.getText(), { size: CONFIG.FONTS.sizes.small, color: CONFIG.COLORS.neutral\_gray, align: SlidesApp.ParagraphAlignment.CENTER }); Â
```
});
drawBottomBarAndFooter(slide, layout, pageNum); Â
}
// diagramïŒMermaid颚ã»ã¬ãŒã³ïŒã«ãŒãïŒèªåç¢å°ïŒ Â
function createDiagramSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'diagramSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'diagramSlide', data.subhead);
const lanes \= Array.isArray(data.lanes) ? data.lanes : \[\]; Â
const area0 \= layout.getRect('diagramSlide.lanesArea'); Â
const area \= offsetRect(area0, 0, dy);
const px \= (p)=\> layout.pxToPt(p); Â
const laneGap \= px(CONFIG.DIAGRAM.laneGap\_px); Â
const lanePad \= px(CONFIG.DIAGRAM.lanePad\_px); Â
const laneTitleH \= px(CONFIG.DIAGRAM.laneTitle\_h\_px); Â
const cardGap \= px(CONFIG.DIAGRAM.cardGap\_px); Â
const cardMinH \= px(CONFIG.DIAGRAM.cardMin\_h\_px); Â
const cardMaxH \= px(CONFIG.DIAGRAM.cardMax\_h\_px); Â
const arrowH \= px(CONFIG.DIAGRAM.arrow\_h\_px); Â
const arrowGap \= px(CONFIG.DIAGRAM.arrowGap\_px);
const n \= Math.max(1, lanes.length); Â
const laneW \= (area.width \- laneGap \* (n \- 1)) / n;
const cardBoxes \= \[\];
for (let j \= 0; j \< n; j++) { Â
const lane \= lanes\[j\] || { title: '', items: \[\] }; Â
const left \= area.left \+ j \* (laneW \+ laneGap); Â
const top \= area.top;
```
const lt \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, left, top, laneW, laneTitleH); Â
lt.getFill().setSolidFill(CONFIG.COLORS.lane\_title\_bg); Â
lt.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.lane\_border); Â
lt.getBorder().setWeight(1); Â
lt.getText().setText(lane.title || ''); Â
applyTextStyle(lt.getText(), { size: CONFIG.FONTS.sizes.laneTitle, bold: true, align: SlidesApp.ParagraphAlignment.CENTER });
const items \= Array.isArray(lane.items) ? lane.items : \[\]; Â
const availH \= area.height \- laneTitleH \- lanePad \* 2; Â
const rows \= Math.max(1, items.length); Â
const idealH \= (availH \- cardGap \* (rows \- 1)) / rows; Â
const cardH \= Math.max(cardMinH, Math.min(cardMaxH, idealH)); Â
const totalH \= cardH \* rows \+ cardGap \* (rows \- 1); Â
const firstTop \= top \+ laneTitleH \+ lanePad \+ Math.max(0, (availH \- totalH) / 2);
cardBoxes\[j\] \= \[\]; Â
for (let i \= 0; i \< rows; i++) { Â
 const cardTop \= firstTop \+ i \* (cardH \+ cardGap); Â
 const cardLeft \= left \+ lanePad; Â
 const cardWidth \= laneW \- lanePad \* 2;
 const card \= slide.insertShape(SlidesApp.ShapeType.ROUND\_RECTANGLE, cardLeft, cardTop, cardWidth, cardH); Â
 card.getFill().setSolidFill(CONFIG.COLORS.card\_bg); Â
 card.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.card\_border); Â
 card.getBorder().setWeight(1); Â
 setStyledText(card, items\[i\] || '', { size: CONFIG.FONTS.sizes.body });
 try { card.setContentAlignment(SlidesApp.ContentAlignment.MIDDLE); } catch(e){} Â
 cardBoxes\[j\]\[i\] \= { left: cardLeft, top: cardTop, width: cardWidth, height: cardH }; Â
} Â
```
}
// åè¡ã«ãŒãéãç¢å°ã§æ¥ç¶ Â
const maxRows \= Math.max(...cardBoxes.map(a \=\> a.length)); Â
for (let j \= 0; j \< n \- 1; j++) { Â
const L \= cardBoxes\[j\], R \= cardBoxes\[j \+ 1\]; Â
for (let i \= 0; i \< maxRows; i++) { Â
const a \= L\[i\], b \= R\[i\]; Â
if (a && b) drawArrowBetweenRects(slide, a, b, arrowH, arrowGap); Â
} Â
}
drawBottomBarAndFooter(slide, layout, pageNum); Â
}
// cardsïŒã°ã¬ãŒæ ã®ã¿ïŒâ title/desc äž¡æ¹ã§ã€ã³ã©ã€ã³è£
食ãæå¹å Â
function createCardsSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'cardsSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'cardsSlide', data.subhead);
const area \= offsetRect(layout.getRect('cardsSlide.gridArea'), 0, dy); Â
const items \= Array.isArray(data.items) ? data.items : \[\]; Â
const cols \= Math.min(3, Math.max(2, Number(data.columns) || (items.length \<= 4 ? 2 : 3))); Â
const gap \= layout.pxToPt(16); Â
const rows \= Math.ceil(items.length / cols); Â
const cardW \= (area.width \- gap \* (cols \- 1)) / cols; Â
const cardH \= Math.max(layout.pxToPt(92), (area.height \- gap \* (rows \- 1)) / rows);
for (let idx \= 0; idx \< items.length; idx++) { Â
const r \= Math.floor(idx / cols), c \= idx % cols; Â
const left \= area.left \+ c \* (cardW \+ gap); Â
const top  \= area.top  \+ r \* (cardH \+ gap);
```
const card \= slide.insertShape(SlidesApp.ShapeType.ROUND\_RECTANGLE, left, top, cardW, cardH); Â
card.getFill().setSolidFill(CONFIG.COLORS.card\_bg); Â
card.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.card\_border); Â
card.getBorder().setWeight(1);
const obj \= items\[idx\]; Â
if (typeof obj \=== 'string') { Â
 setStyledText(card, obj, { size: CONFIG.FONTS.sizes.body }); Â
} else { Â
 const title \= String(obj.title || ''); Â
 const desc  \= String(obj.desc || ''); Â
 const combined \= \`${title}${desc ? '\\n' \+ desc : ''}\`; Â
 setStyledText(card, combined, { size: CONFIG.FONTS.sizes.body }); Â
 if (title.length \> 0\) { Â
  try { card.getText().getRange(0, title.length).getTextStyle().setBold(true); } catch(e){} Â
 } Â
} Â
try { card.setContentAlignment(SlidesApp.ContentAlignment.MIDDLE); } catch(e) {} Â
```
}
drawBottomBarAndFooter(slide, layout, pageNum); Â
}
// tableïŒSlidesããŒãã«ã§ãã€ã³ã©ã€ã³è£
食察å¿ã倱ææã¯ç©åœ¢ä»£æ¿ã§ã察å¿ïŒ Â
function createTableSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'tableSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'tableSlide', data.subhead);
const area \= offsetRect(layout.getRect('tableSlide.area'), 0, dy); Â
const headers \= Array.isArray(data.headers) ? data.headers : \[\]; Â
const rows \= Array.isArray(data.rows) ? data.rows : \[\];
try { Â
if (headers.length \> 0\) { Â
const table \= slide.insertTable(rows.length \+ 1, headers.length); Â
table.setLeft(area.left).setTop(area.top).setWidth(area.width); Â
for (let c \= 0; c \< headers.length; c++) { Â
const cell \= table.getCell(0, c); Â
setStyledText(cell, String(headers\[c\] || ''), { bold: true, align: SlidesApp.ParagraphAlignment.CENTER }); Â
} Â
for (let r \= 0; r \< rows.length; r++) { Â
const row \= rows\[r\] || \[\]; Â
for (let c \= 0; c \< headers.length; c++) { Â
const cell \= table.getCell(r \+ 1, c); Â
setStyledText(cell, String(row\[c\] || ''), { align: SlidesApp.ParagraphAlignment.CENTER }); Â
} Â
} Â
} else { Â
throw new Error('headers is empty'); Â
} Â
} catch (e) { Â
const cols \= Math.max(1, headers.length || 3); Â
const rcount \= rows.length \+ 1; Â
const gap \= layout.pxToPt(1); Â
const cellW \= (area.width \- gap \* (cols \- 1)) / cols; Â
const cellH \= (area.height \- gap \* (rcount \- 1)) / rcount; Â
const drawCell \= (r, c, text, bold) \=\> { Â
const left \= area.left \+ c \* (cellW \+ gap); Â
const top  \= area.top  \+ r \* (cellH \+ gap); Â
const cell \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, left, top, cellW, cellH); Â
cell.getFill().setSolidFill(CONFIG.COLORS.background\_white); Â
cell.getBorder().getLineFill().setSolidFill(CONFIG.COLORS.card\_border); Â
cell.getBorder().setWeight(1); Â
setStyledText(cell, String(text || ''), { bold: \!\!bold, align: SlidesApp.ParagraphAlignment.CENTER }); Â
try { cell.setContentAlignment(SlidesApp.ContentAlignment.MIDDLE); } catch(e){} Â
}; Â
(headers.length ? headers : \['é
ç®','å€1','å€2'\]).forEach((h, c) \=\> drawCell(0, c, h, true)); Â
for (let r \= 0; r \< rows.length; r++) { Â
const row \= rows\[r\] || \[\]; Â
for (let c \= 0; c \< (headers.length || 3); c++) drawCell(r \+ 1, c, row\[c\], false); Â
} Â
}
drawBottomBarAndFooter(slide, layout, pageNum); Â
}
// progressïŒé²æããŒïŒ Â
function createProgressSlide(slide, data, layout, pageNum) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
drawStandardTitleHeader(slide, layout, 'progressSlide', data.title); Â
const dy \= drawSubheadIfAny(slide, layout, 'progressSlide', data.subhead);
const area \= offsetRect(layout.getRect('progressSlide.area'), 0, dy); Â
const items \= Array.isArray(data.items) ? data.items : \[\]; Â
const n \= Math.max(1, items.length); Â
const rowH \= area.height / n;
for (let i \= 0; i \< n; i++) { Â
const y \= area.top \+ i \* rowH \+ layout.pxToPt(6); Â
const label \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, area.left, y, layout.pxToPt(150), layout.pxToPt(18)); Â
setStyledText(label, String(items\[i\].label || ''), { size: CONFIG.FONTS.sizes.body });
```
const barLeft \= area.left \+ layout.pxToPt(160); Â
const barW Â Â \= area.width \- layout.pxToPt(210); Â
const barBG \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, barLeft, y, barW, layout.pxToPt(14)); Â
barBG.getFill().setSolidFill(CONFIG.COLORS.faint\_gray); barBG.getBorder().setTransparent();
const p \= Math.max(0, Math.min(100, Number(items\[i\].percent || 0))); Â
const barFG \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, barLeft, y, barW \* (p/100), layout.pxToPt(14)); Â
barFG.getFill().setSolidFill(CONFIG.COLORS.google\_green); barFG.getBorder().setTransparent();
const pct \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, barLeft \+ barW \+ layout.pxToPt(6), y \- layout.pxToPt(1), layout.pxToPt(40), layout.pxToPt(16)); Â
pct.getText().setText(String(p) \+ '%'); Â
applyTextStyle(pct.getText(), { size: CONFIG.FONTS.sizes.small, color: CONFIG.COLORS.neutral\_gray }); Â
```
}
drawBottomBarAndFooter(slide, layout, pageNum); Â
}
function createClosingSlide(slide, data, layout) { Â
slide.getBackground().setSolidFill(CONFIG.COLORS.background\_white); Â
const image \= slide.insertImage(CONFIG.LOGOS.closing); Â
const imgW\_pt \= layout.pxToPt(450) \* layout.scaleX; Â
const aspect \= image.getHeight() / image.getWidth(); Â
image.setWidth(imgW\_pt).setHeight(imgW\_pt \* aspect); Â
image.setLeft((layout.pageW\_pt \- imgW\_pt) / 2).setTop((layout.pageH\_pt \- (imgW\_pt \* aspect)) / 2); Â
}
// \--- 7\. ãŠãŒãã£ãªãã£é¢æ°çŸ€ \--- Â
function createLayoutManager(pageW\_pt, pageH\_pt) { Â
const pxToPt \= (px) \=\> px \* 0.75; Â
const baseW\_pt \= pxToPt(CONFIG.BASE\_PX.W); Â
const baseH\_pt \= pxToPt(CONFIG.BASE\_PX.H); Â
const scaleX \= pageW\_pt / baseW\_pt; Â
const scaleY \= pageH\_pt / baseH\_pt;
const getPositionFromPath \= (path) \=\> path.split('.').reduce((obj, key) \=\> obj\[key\], CONFIG.POS\_PX); Â
return { Â
scaleX, scaleY, pageW\_pt, pageH\_pt, pxToPt, Â
getRect: (spec) \=\> { Â
const pos \= typeof spec \=== 'string' ? getPositionFromPath(spec) : spec; Â
let left\_px \= pos.left; Â
if (pos.right \!== undefined && pos.left \=== undefined) { Â
left\_px \= CONFIG.BASE\_PX.W \- pos.right \- pos.width; Â
} Â
return { Â
left: Â left\_px \!== undefined ? pxToPt(left\_px) \* scaleX : undefined, Â
top: Â Â pos.top \!== undefined ? pxToPt(pos.top) \* scaleY : undefined, Â
width: Â pos.width \!== undefined ? pxToPt(pos.width) \* scaleX : undefined, Â
height: pos.height \!== undefined ? pxToPt(pos.height) \* scaleY : undefined, Â
}; Â
} Â
}; Â
}
function offsetRect(rect, dx, dy) { Â
return { left: rect.left \+ (dx || 0), top: rect.top \+ (dy || 0), width: rect.width, height: rect.height }; Â
}
function drawStandardTitleHeader(slide, layout, key, title) { Â
const logoRect \= layout.getRect(\`${key}.headerLogo\`); Â
const logo \= slide.insertImage(CONFIG.LOGOS.header); Â
const asp \= logo.getHeight() / logo.getWidth(); Â
logo.setLeft(logoRect.left).setTop(logoRect.top).setWidth(logoRect.width).setHeight(logoRect.width \* asp);
const titleRect \= layout.getRect(\`${key}.title\`); Â
const titleShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, titleRect.left, titleRect.top, titleRect.width, titleRect.height); Â
setStyledText(titleShape, title || '', { size: CONFIG.FONTS.sizes.contentTitle, bold: true });
const uRect \= layout.getRect(\`${key}.titleUnderline\`); Â
const u \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, uRect.left, uRect.top, uRect.width, uRect.height); Â
u.getFill().setSolidFill(CONFIG.COLORS.primary\_blue); Â
u.getBorder().setTransparent(); Â
}
function drawSubheadIfAny(slide, layout, key, subhead) { Â
if (\!subhead) return 0; Â
const rect \= layout.getRect(\`${key}.subhead\`); Â
const box \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, rect.left, rect.top, rect.width, rect.height); Â
setStyledText(box, subhead, { size: CONFIG.FONTS.sizes.subhead, color: CONFIG.COLORS.text\_primary }); Â
return layout.pxToPt(36); Â
}
function drawBottomBar(slide, layout) { Â
const barRect \= layout.getRect('bottomBar'); Â
const bar \= slide.insertShape(SlidesApp.ShapeType.RECTANGLE, barRect.left, barRect.top, barRect.width, barRect.height); Â
bar.getFill().setSolidFill(CONFIG.COLORS.primary\_blue); Â
bar.getBorder().setTransparent(); Â
}
function drawBottomBarAndFooter(slide, layout, pageNum) { Â
drawBottomBar(slide, layout); Â
addGoogleFooter(slide, layout, pageNum); Â
}
function addGoogleFooter(slide, layout, pageNum) { Â
const leftRect \= layout.getRect('footer.leftText'); Â
const leftShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, leftRect.left, leftRect.top, leftRect.width, leftRect.height); Â
leftShape.getText().setText(CONFIG.FOOTER\_TEXT); Â
applyTextStyle(leftShape.getText(), { size: CONFIG.FONTS.sizes.footer, color: CONFIG.COLORS.text\_primary });
if (pageNum \> 0\) { Â
const rightRect \= layout.getRect('footer.rightPage'); Â
const rightShape \= slide.insertShape(SlidesApp.ShapeType.TEXT\_BOX, rightRect.left, rightRect.top, rightRect.width, rightRect.height); Â
rightShape.getText().setText(String(pageNum)); Â
applyTextStyle(rightShape.getText(), { size: CONFIG.FONTS.sizes.footer, color: CONFIG.COLORS.primary\_blue, align: SlidesApp.ParagraphAlignment.END }); Â
} Â
}
function applyTextStyle(textRange, opt) { Â
const style \= textRange.getTextStyle(); Â
style.setFontFamily(CONFIG.FONTS.family); Â
style.setForegroundColor(opt.color || CONFIG.COLORS.text\_primary); Â
style.setFontSize(opt.size || CONFIG.FONTS.sizes.body); Â
style.setBold(opt.bold || false); Â
if (opt.align) { Â
try { textRange.getParagraphs().forEach(p \=\> p.getRange().getParagraphStyle().setParagraphAlignment(opt.align)); } catch (e) {} Â
} Â
}
function setStyledText(shapeOrCell, rawText, baseOpt) { Â
const parsed \= parseInlineStyles(rawText || ''); Â
const tr \= shapeOrCell.getText(); Â
tr.setText(parsed.output); Â
applyTextStyle(tr, baseOpt || {}); Â
applyStyleRanges(tr, parsed.ranges); Â
}
function setBulletsWithInlineStyles(shape, points) { Â
const joiner \= '\\n\\n'; Â
let combined \= ''; Â
const ranges \= \[\];
(points || \[\]).forEach((pt, idx) \=\> { Â
const parsed \= parseInlineStyles(String(pt || '')); Â
const bullet \= '⢠' \+ parsed.output; Â
if (idx \> 0\) combined \+= joiner; Â
const start \= combined.length; Â
combined \+= bullet;
```
parsed.ranges.forEach(r \=\> { Â
 ranges.push({ start: start \+ 2 \+ r.start, end: start \+ 2 \+ r.end, bold: r.bold, color: r.color }); Â
}); Â
```
});
const tr \= shape.getText(); Â
tr.setText(combined || '⢠â'); Â
applyTextStyle(tr, { size: CONFIG.FONTS.sizes.body });
try { Â
tr.getParagraphs().forEach(p \=\> { Â
const ps \= p.getRange().getParagraphStyle(); Â
ps.setLineSpacing(100); Â
ps.setSpaceBelow(6); Â
}); Â
} catch (e) {}
applyStyleRanges(tr, ranges); Â
}
function parseInlineStyles(s) { Â
const ranges \= \[\]; Â
let out \= ''; Â
for (let i \= 0; i \< s.length; ) { Â
// \[\[é倪å\]\] Â
if (s\[i\] \=== '\[' && s\[i+1\] \=== '\[') { Â
const close \= s.indexOf('\]\]', i \+ 2); Â
if (close \!== \-1) { Â
const content \= s.substring(i \+ 2, close); Â
const start \= out.length; Â
out \+= content; Â
const end \= out.length; Â
ranges.push({ start, end, bold: true, color: CONFIG.COLORS.primary\_blue }); Â
i \= close \+ 2; continue; Â
} Â
} Â
// \*\*倪å\*\* Â
if (s\[i\] \=== '\*' && s\[i+1\] \=== '\*') { Â
const close \= s.indexOf('\*\*', i \+ 2); Â
if (close \!== \-1) { Â
const content \= s.substring(i \+ 2, close); Â
const start \= out.length; Â
out \+= content; Â
const end \= out.length; Â
ranges.push({ start, end, bold: true }); Â
i \= close \+ 2; continue; Â
} Â
} Â
out \+= s\[i\]; i++; Â
} Â
return { output: out, ranges }; Â
}
function applyStyleRanges(textRange, ranges) { Â
ranges.forEach(r \=\> { Â
try { Â
const sub \= textRange.getRange(r.start, r.end); Â
if (\!sub) return; Â
const st \= sub.getTextStyle(); Â
if (r.bold) Â st.setBold(true); Â
if (r.color) st.setForegroundColor(r.color); Â
} catch (e) {} Â
}); Â
}
function normalizeImages(arr) { Â
return (arr || \[\]).map(v \=\> { Â
if (typeof v \=== 'string') return { url: v }; Â
if (v && typeof v.url \=== 'string') return { url: v.url, caption: v.caption || '' }; Â
return null; Â
}).filter(Boolean).slice(0, 6); Â
}
function renderImagesInArea(slide, layout, area, images) { Â
if (\!images || images.length \=== 0\) return; Â
const n \= Math.min(6, images.length); Â
let cols \= 1, rows \= 1; Â
if (n \=== 1\) { cols \= 1; rows \= 1; } Â
else if (n \=== 2\) { cols \= 2; rows \= 1; } Â
else if (n \<= 4\) { cols \= 2; rows \= 2; } Â
else { cols \= 3; rows \= 2; }
const gap \= layout.pxToPt(10); Â
const cellW \= (area.width \- gap \* (cols \- 1)) / cols; Â
const cellH \= (area.height \- gap \* (rows \- 1)) / rows;
for (let i \= 0; i \< n; i++) { Â
const r \= Math.floor(i / cols), c \= i % cols; Â
const left \= area.left \+ c \* (cellW \+ gap); Â
const top  \= area.top  \+ r \* (cellH \+ gap); Â
try { Â
const img \= slide.insertImage(images\[i\].url); Â
const scale \= Math.min(cellW / img.getWidth(), cellH / img.getHeight()); Â
const w \= img.getWidth() \* scale; Â
const h \= img.getHeight() \* scale; Â
img.setWidth(w).setHeight(h); Â
img.setLeft(left \+ (cellW \- w) / 2).setTop(top \+ (cellH \- h) / 2); Â
} catch(e) {} Â
} Â
}
function isAgendaTitle(title) { Â
const t \= String(title || '').toLowerCase(); Â
return /(agenda|ã¢ãžã§ã³ã|ç®æ¬¡|æ¬æ¥ãäŒãããããš)/.test(t); Â
} Â
function buildAgendaFromSlideData() { Â
const pts \= \[\]; Â
for (const d of slideData) { Â
if (d && d.type \=== 'section' && typeof d.title \=== 'string' && d.title.trim()) pts.push(d.title.trim()); Â
} Â
if (pts.length \> 0\) return pts.slice(0, 5); Â
const alt \= \[\]; Â
for (const d of slideData) { Â
if (d && d.type \=== 'content' && typeof d.title \=== 'string' && d.title.trim()) alt.push(d.title.trim()); Â
} Â
return alt.slice(0, 5); Â
}
function drawArrowBetweenRects(slide, a, b, arrowH, arrowGap) { Â
const fromX \= a.left \+ a.width; Â
const toX Â \= b.left; Â
const width \= Math.max(0, toX \- fromX \- arrowGap \* 2); Â
if (width \< 8\) return; Â
const yMid \= ((a.top \+ a.height/2) \+ (b.top \+ b.height/2)) / 2; Â
const top \= yMid \- arrowH / 2; Â
const left \= fromX \+ arrowGap; Â
const arr \= slide.insertShape(SlidesApp.ShapeType.RIGHT\_ARROW, left, top, width, arrowH); Â
arr.getFill().setSolidFill(CONFIG.COLORS.primary\_blue); Â
arr.getBorder().setTransparent(); Â
}  ãã³ãã¬ãŒããã¿ãŒã³ãå¢ãããã
å®å®æ§ãé«ãããã©ãã·ã¥ã¢ããã¯åŒãç¶ãè¡ã£ãŠããäºå®ã§ã
æ°ããŒãžã§ã³ã宿ããããŸãå
±æããŸããïŒ
åèã«ãªã£ããnoteã«ãããããã©ããŒããé¡ãããŸã
Xã§ã®ææ³ã·ã§ã¢ïŒ#ãŸããåŒããã³ããïŒãããã ããã°ïœ€æ¬¡ã®éçºã®ãšãã«ã®ãŒã«ãªããŸãð¥
ãGoogleã¹ã©ã€ããäžç¬ã§å®æãã"å¥è·¡"ã®ããã³ããã
â ãŸããïœAI à Google (@Majin_AppSheet) August 16, 2025
ã¹ã©ã€ãçæAIã¯è²ã ç¥ã£ãŠããã©ãäŒç€Ÿã®ã»ãã¥ãªãã£ããªã·ãŒã§äœ¿ããªãâŠãããªæ¹ãå€ãã®ã§ã¯ïŒ
ä»äºã§äœ¿ããªããšæå³ããªãã§ãããð¥²
ãããªæ©ã¿ã解決ãããããéæ³ã®ããã³ãããç·šã¿åºããŸããïŒ
å¿ èŠãªã®ã¯ãGeminiã ãã pic.twitter.com/ZaqMgHj0C6
ããããã©ã€ã¿ãŒâš