{"id":22945,"date":"2025-11-21T21:57:13","date_gmt":"2025-11-21T12:57:13","guid":{"rendered":"https:\/\/cg-method.com\/google\/?p=22945"},"modified":"2026-09-26T12:31:38","modified_gmt":"2026-09-26T03:31:38","slug":"google-spreadsheet-to-jira-task","status":"publish","type":"post","link":"https:\/\/cg-method.com\/google\/google-spreadsheet-to-jira-task\/","title":{"rendered":"Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u2502\u30b7\u30fc\u30c8\u304b\u3089JIRA\u306e\u30bf\u30b9\u30af\u3092\u4f5c\u6210\u3059\u308b\u65b9\u6cd5"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Jira\u306eREST API\u3068Google Apps Script\uff08GAS\uff09\u3092\u6d3b\u7528\u3057\u3001Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u884c\u30c7\u30fc\u30bf\u304b\u3089Jira\u306e\u30bf\u30b9\u30af\u3092\u4e00\u62ec\u767b\u9332\u3059\u308b\u624b\u9806\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u8ab2\u984c\u30921\u4ef6\u305a\u3064\u624b\u52d5\u767b\u9332\u305b\u305a\u3001\u30b7\u30fc\u30c8\u4e0a\u3067\u30ea\u30b9\u30c8\u5316\u3057\u3066\u30b9\u30af\u30ea\u30d7\u30c8\u304b\u3089\u81ea\u52d5\u4f5c\u6210\u3059\u308b\u3053\u3068\u3067\u4f5c\u696d\u5de5\u6570\u3092\u524a\u6e1b\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"186\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h26_56-1024x186.png\" alt=\"Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u884c\u30c7\u30fc\u30bf\u304b\u3089\u4e00\u62ec\u4f5c\u6210\u3055\u308c\u305fJira\u30bf\u30b9\u30af\u306e\u78ba\u8a8d\u753b\u9762\u3002\" class=\"wp-image-22956\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h26_56-1024x186.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h26_56-300x54.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h26_56-768x139.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h26_56.png 1159w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u4f5c\u6210\u3055\u308c\u305fJira\u30bf\u30b9\u30af\u306e\u78ba\u8a8d\u753b\u9762\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"623\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-1024x623.png\" alt=\"\u4f5c\u6210\u3055\u308c\u305fJira\u30bf\u30b9\u30af\u306e\u78ba\u8a8d\u753b\u9762\u3002\" class=\"wp-image-22955\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-1024x623.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-300x183.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-768x467.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39.png 1264w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u4e0a\u306e\u753b\u50cf\u30c7\u30fc\u30bf\u3092Jira\u30bf\u30b9\u30af\u306e\u8aac\u660e\u6b04\u3078\u57cb\u3081\u8fbc\u3080\u6307\u5b9a\u306b\u3082\u5bfe\u5fdc\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"254\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-1024x254.png\" alt=\"Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u4e0a\u306e\u753b\u50cf\u30c7\u30fc\u30bf\u3092Jira\u30bf\u30b9\u30af\u306e\u8aac\u660e\u6b04\u3078\u57cb\u3081\u8fbc\u3093\u3060\u8868\u793a\u4f8b\u3002\" class=\"wp-image-22950\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-1024x254.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-300x74.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-768x191.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59.png 1140w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"605\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-1024x605.png\" alt=\"Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u304b\u3089Jira\u306e\u30bf\u30b9\u30af\u3092\u4f5c\u6210\u3059\u308b\u9023\u643a\u624b\u9806\u306e\u6982\u8981\u3092\u793a\u3059\u753b\u9762\u3002\" class=\"wp-image-22962\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-1024x605.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-300x177.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-768x454.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48.png 1399w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e8b\u524d\u6e96\u5099\uff1a\u9023\u643a\u306b\u5fc5\u8981\u306a3\u3064\u306eJira\u60c5\u5831\u3092\u78ba\u8a8d\u3059\u308b<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">GAS\u304b\u3089Jira API\u3078\u8a8d\u8a3c\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u9001\u308b\u305f\u3081\u3001\u4e8b\u524d\u306b\u4ee5\u4e0b\u306e3\u9805\u76ee\u3092\u7528\u610f\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong><strong>1. Jira Cloud\u306eURL<\/strong><\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5229\u7528\u4e2d\u306eAtlassian\u7d44\u7e54\u307e\u305f\u306f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u30a2\u30af\u30bb\u30b9\u3059\u308b\u30d9\u30fc\u30b9URL\u3067\u3059\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u4f8b: <code>https:\/\/xxxxx.atlassian.net<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Jira\u30ed\u30b0\u30a4\u30f3\u7528\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Jira\u30a2\u30ab\u30a6\u30f3\u30c8\u306b\u767b\u9332\u3057\u3066\u3044\u308b\u30ed\u30b0\u30a4\u30f3\u7528\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Jira API\u30c8\u30fc\u30af\u30f3<\/h3>\n\n\n\n<ul class=\"wp-block-list is-style-num_circle\">\n<li>Atlassian\u30a2\u30ab\u30a6\u30f3\u30c8\u3078\u30ed\u30b0\u30a4\u30f3<\/li>\n\n\n\n<li>\u53f3\u4e0a\u306e\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u30a2\u30a4\u30b3\u30f3\u304b\u3089\u300c\u30a2\u30ab\u30a6\u30f3\u30c8\u8a2d\u5b9a\u300d\u2192\u300c\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u300d\u2192\u300cAPI\u30c8\u30fc\u30af\u30f3\u300d\u306e\u9806\u306b\u958b\u304f<\/li>\n\n\n\n<li>\u300cAPI\u30c8\u30fc\u30af\u30f3\u3092\u4f5c\u6210\u300d\u3092\u9078\u629e\u3057\u3001\u30e9\u30d9\u30eb\u3092\u6307\u5b9a\u3057\u3066\u65b0\u898f\u4f5c\u6210<\/li>\n\n\n\n<li>\u751f\u6210\u3055\u308c\u305f\u30c8\u30fc\u30af\u30f3\u6587\u5b57\u5217\u3092\u30b3\u30d4\u30fc\uff08\u518d\u8868\u793a\u3067\u304d\u306a\u3044\u305f\u3081\u63a7\u3048\u3066\u304a\u304f\uff09<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3067API\u9023\u643a\u306b\u5fc5\u8981\u306a\u8a8d\u8a3c\u60c5\u5831\u304c\u63c3\u3044\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"253\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h07_40-1024x253.png\" alt=\"Atlassian\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u8a2d\u5b9a\u3067\u4f5c\u6210\u3057\u305fAPI\u30c8\u30fc\u30af\u30f3\u6587\u5b57\u5217\u306e\u78ba\u8a8d\u753b\u9762\u3002\" class=\"wp-image-22946\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h07_40-1024x253.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h07_40-300x74.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h07_40-768x189.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h07_40.png 1496w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">GAS\u306e\u8a2d\u5b9a\uff08\u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u767b\u9332\uff09<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u300c\u62e1\u5f35\u6a5f\u80fd\u300d\u2192\u300cApps Script\u300d\u3092\u958b\u304d\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u8a2d\u5b9a\u304b\u3089\u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"910\" height=\"1024\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h17_30-910x1024.png\" alt=\"Google Apps Script\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u8a2d\u5b9a\u3067\u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u8ffd\u52a0\u3059\u308b\u753b\u9762\u3002\" class=\"wp-image-22947\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h17_30-910x1024.png 910w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h17_30-267x300.png 267w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h17_30-768x864.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h17_30.png 976w\" sizes=\"auto, (max-width: 910px) 100vw, 910px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u30d7\u30ed\u30d1\u30c6\u30a3\u540d<\/th><th>\u5024\u306e\u4f8b<\/th><\/tr><\/thead><tbody><tr><td>JIRA_BASE_URL<\/td><td><code>https:\/\/xxxxx.atlassian.net<\/code><\/td><\/tr><tr><td>JIRA_EMAIL<\/td><td><code>\u3042\u306a\u305f\u306e\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9<\/code><\/td><\/tr><tr><td>JIRA_API_TOKEN<\/td><td>\u53d6\u5f97\u3057\u305fAPI\u30c8\u30fc\u30af\u30f3\u6587\u5b57\u5217<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u8a8d\u8a3c\u60c5\u5831\u3092\u30cf\u30fc\u30c9\u30b3\u30fc\u30c9\u305b\u305a\u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u3078\u4fdd\u5b58\u3059\u308b\u3053\u3068\u3067\u3001\u5b89\u5168\u306bAPI\u3092\u547c\u3073\u51fa\u305b\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"812\" height=\"488\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h20_03.png\" alt=\"\u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u306bJira\u306e\u63a5\u7d9a\u60c5\u5831\u3084\u30c8\u30fc\u30af\u30f3\u3092\u8a2d\u5b9a\u3057\u305f\u72b6\u614b\u306e\u753b\u9762\u3002\" class=\"wp-image-22948\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h20_03.png 812w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h20_03-300x180.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_18h20_03-768x462.png 768w\" sizes=\"auto, (max-width: 812px) 100vw, 812px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u7d9a\u3044\u3066\u3001\u30b7\u30fc\u30c8\u5074\u306b\u767b\u9332\u7528\u30c7\u30fc\u30bf\u3092\u8a18\u8ff0\u3057\u3066\u5b9f\u884c\u6e96\u5099\u3092\u884c\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u30b7\u30fc\u30c8\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3068\u30bf\u30b9\u30af\u767b\u9332\u306e\u5b9f\u884c<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u5bfe\u8c61\u30b7\u30fc\u30c8\uff08\u4f8b: \u30b7\u30fc\u30c81\uff09\u306b\u5404\u5217\u306e\u898b\u51fa\u3057\u3068\u4f5c\u6210\u3057\u305f\u3044\u30bf\u30b9\u30af\u306e\u5024\u3092\u5165\u529b\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>\u767a\u884c\u72b6\u614b<\/th><th>\u89aa<\/th><th>\u30bf\u30b9\u30af\u756a\u53f7<\/th><th>\u5831\u544a\u8005<\/th><th>\u30bf\u30b9\u30af\u540d<\/th><th>\u62c5\u5f53\u8005<\/th><th>\u30b9\u30c6\u30fc\u30bf\u30b9<\/th><th>\u512a\u5148\u5ea6<\/th><th>\u8aac\u660e<\/th><\/tr><\/thead><tbody><tr><td><\/td><td>MFLP-2<\/td><td><\/td><td>yamada<\/td><td>\u30bf\u30b9\u30af\u4f5c\u6210\u30c6\u30b9\u30c8<\/td><td>tanaka<\/td><td>\u9032\u884c\u4e2d<\/td><td>Low<\/td><td>\u30bf\u30b9\u30af\u4f5c\u6210\u30c6\u30b9\u30c8\u306e\u8aac\u660e<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"is-style-icon_pen wp-block-paragraph\">\u300c\u767a\u884c\u72b6\u614b\u300d\u5217\u3068\u300c\u30bf\u30b9\u30af\u756a\u53f7\u300d\u5217\u306f\u3001\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u5b9f\u884c\u5b8c\u4e86\u5f8c\u306b\u4f5c\u6210\u7d50\u679c\u304c\u81ea\u52d5\u8ffd\u8a18\u3055\u308c\u307e\u3059\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u30b9\u30af\u30ea\u30d7\u30c8\u30a8\u30c7\u30a3\u30bf\u306b\u5bfe\u8c61\u306e\u30b3\u30fc\u30c9\u3092\u8cbc\u308a\u4ed8\u3051\u3001\u95a2\u6570<code><strong>publishJiraTasksFromSheet()<\/strong><\/code>\u3092\u9078\u629e\u3057\u3066\u5b9f\u884c\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u95a2\u9023\u64cd\u4f5c\u3084\u5fdc\u7528\u4e8b\u4f8b\u306f\u3001\u95a2\u9023\u8a18\u4e8b\u306e\u307e\u3068\u3081\u3092\u3054\u78ba\u8a8d\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<div class=\"swell-block-postLink\">\t\t\t<div class=\"p-blogCard -internal\" data-type=\"type1\" data-onclick=\"clickLink\">\n\t\t\t\t<div class=\"p-blogCard__inner\">\n\t\t\t\t\t<span class=\"p-blogCard__caption\">\u3042\u308f\u305b\u3066\u8aad\u307f\u305f\u3044<\/span>\n\t\t\t\t\t<div class=\"p-blogCard__thumb c-postThumb\"><figure class=\"c-postThumb__figure\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2026\/09\/google-apps-matome-3-300x169.jpg\" alt=\"\" class=\"c-postThumb__img u-obf-cover\" width=\"320\" height=\"180\"><\/figure><\/div>\t\t\t\t\t<div class=\"p-blogCard__body\">\n\t\t\t\t\t\t<a class=\"p-blogCard__title\" href=\"https:\/\/cg-method.com\/google\/google-apps-matome\/\">Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u30fb\u30c9\u30e9\u30a4\u30d6\u306e\u4f7f\u3044\u65b9\u307e\u3068\u3081\uff5c\u95a2\u6570\u3068GAS<\/a>\n\t\t\t\t\t\t<span class=\"p-blogCard__excerpt\">Google\u306e\u64cd\u4f5c\u3092\u300c\u4f55\u3092\u3057\u305f\u3044\u304b\u300d\u304b\u3089\u63a2\u305b\u308b\u30ac\u30a4\u30c9\u3067\u3059\u3002 \u307e\u305a\u6a19\u6e96\u306e\u753b\u9762\u64cd\u4f5c\u3084\u95a2\u6570\u3067\u89e3\u6c7a\u3067\u304d\u308b\u304b\u3092\u78ba\u8a8d\u3057\u3001\u7e70\u308a\u8fd4\u3059\u51e6\u7406\u306bGAS\u3092\u4f7f\u3044\u307e\u3059\u3002 \u76ee\u7684\u304b\u3089\u624b\u9806\u3092\u9078\u3076 \u3084\u308a\u305f&#8230;<\/span>\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\n\n<p class=\"wp-block-paragraph\">\u30b3\u30fc\u30c9\u5074\u3067\u53c2\u7167\u3059\u308b\u30b7\u30fc\u30c8\u540d\u304c\u300c\u30b7\u30fc\u30c81\u300d\u4ee5\u5916\u306e\u5834\u5408\u306f\u3001\u5b9a\u6570\u5b9a\u7fa9\u306e\u30b7\u30fc\u30c8\u540d\u3092\u5b9f\u969b\u306e\u540d\u79f0\u306b\u5408\u308f\u305b\u3066\u4fee\u6b63\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>const sheet = ss.getSheetByName('\u30b7\u30fc\u30c81') || ss.getActiveSheet();<\/code><\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-js\" data-lang=\"JavaScript\"><code>\/************************************************\n * Jira \u30bf\u30b9\u30af\u767a\u884c\u30b9\u30af\u30ea\u30d7\u30c8\n * \uff08\u30a8\u30d4\u30c3\u30af\u7d10\u4ed8\u3051 + \u62c5\u5f53\u8005 + \u30b9\u30c6\u30fc\u30bf\u30b9 + \u512a\u5148\u5ea6\n *\n * \u30b7\u30fc\u30c8\u69cb\u6210\uff08\u30b7\u30fc\u30c81\uff09\n *   A: \u767a\u884c\u72b6\u614b   \uff08\u7a7a \/ \u6e08\uff09\n *   B: \u89aa         \uff08\u30a8\u30d4\u30c3\u30af\u30ad\u30fc: \u4f8b MFLP-2\uff09\n *   C: \u30bf\u30b9\u30af\u756a\u53f7\uff08Jira Issue\u30ad\u30fc\uff09\n *   D: \u5831\u544a\u8005     \uff08\u672a\u4f7f\u7528\uff09\n *   E: \u30bf\u30b9\u30af\u540d   \uff08summary\uff09\n *   F: \u62c5\u5f53\u8005     \uff08Jira\u306e\u8868\u793a\u540d: \u4f8b suimin\uff09\n *   G: \u30b9\u30c6\u30fc\u30bf\u30b9 \uff08To Do \/ \u9032\u884c\u4e2d \/ \u30ec\u30d3\u30e5\u30fc\u4e2d \/ \u5b8c\u4e86\uff09\n *   H: \u512a\u5148\u5ea6     \uff08Highest \/ High \/ Medium \/ Low \/ Lowest\uff09\n *   I: \u8aac\u660e       \uff08\u30c6\u30ad\u30b9\u30c8\uff09\n ************************************************\/\n\n\n\/* ========================\n   \u5171\u901a\n======================== *\/\n\nfunction getJiraConfig() {\n  const props    = PropertiesService.getScriptProperties();\n  const baseUrl  = props.getProperty(&#39;JIRA_BASE_URL&#39;);\n  const email    = props.getProperty(&#39;JIRA_EMAIL&#39;);\n  const apiToken = props.getProperty(&#39;JIRA_API_TOKEN&#39;);\n\n  if (!baseUrl || !email || !apiToken) {\n    throw new Error(&#39;Jira\u63a5\u7d9a\u60c5\u5831\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002&#39;);\n  }\n  return { baseUrl, email, apiToken };\n}\n\n\/**\n * \u30ad\u30fc\u3092HYPERLINK\u306b\u5909\u63db\u3057\u3066\u30bb\u30eb\u3078\u30bb\u30c3\u30c8\n *\/\nfunction setJiraLinkToCell_(sheet, row, col, issueKey) {\n  if (!issueKey) return;\n  const config = getJiraConfig();\n  const url = config.baseUrl.replace(\/\\\/$\/, &#39;&#39;) + &#39;\/browse\/&#39; + issueKey;\n  sheet.getRange(row, col).setFormula(\n    `=HYPERLINK(&quot;${url}&quot;,&quot;${issueKey}&quot;)`\n  );\n}\n\n\n\/* ========================\n   \u30e6\u30fc\u30b6\u30fc\u691c\u7d22\uff08\u62c5\u5f53\u8005\uff09\n======================== *\/\n\nfunction findAccountIdByExactDisplayName_(displayName) {\n  const config = getJiraConfig();\n  const url = config.baseUrl + &#39;\/rest\/api\/3\/user\/search?query=&#39; +\n              encodeURIComponent(displayName);\n\n  const res = UrlFetchApp.fetch(url, {\n    method: &#39;get&#39;,\n    headers: {\n      Authorization: &#39;Basic &#39; +\n        Utilities.base64Encode(config.email + &#39;:&#39; + config.apiToken)\n    },\n    muteHttpExceptions: true\n  });\n\n  if (res.getResponseCode() &gt;= 300) {\n    Logger.log(&#39;\u30e6\u30fc\u30b6\u30fc\u691c\u7d22\u30a8\u30e9\u30fc: &#39; + res.getContentText());\n    return &#39;&#39;;\n  }\n\n  const users = JSON.parse(res.getContentText());\n  for (const user of users) {\n    if (user.displayName === displayName) return user.accountId;\n  }\n  return &#39;&#39;;\n}\n\n\n\/* ========================\n   \u30b9\u30c6\u30fc\u30bf\u30b9\u9077\u79fb\n======================== *\/\n\n\/**\n * G\u5217\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u540d\uff08\u300c\u30ec\u30d3\u30e5\u30fc\u4e2d\u300d\u300c\u9032\u884c\u4e2d\u300d\u300c\u5b8c\u4e86\u300d\u306a\u3069\uff09\u306b\u9077\u79fb\u3055\u305b\u308b\n *\/\nfunction transitionIssueStatus(issueKey, targetStatusName) {\n  if (!targetStatusName) return;\n\n  const config = getJiraConfig();\n  const url = config.baseUrl + &#39;\/rest\/api\/3\/issue\/&#39; +\n              encodeURIComponent(issueKey) + &#39;\/transitions&#39;;\n\n  const headers = {\n    Authorization: &#39;Basic &#39; +\n      Utilities.base64Encode(config.email + &#39;:&#39; + config.apiToken),\n    Accept: &#39;application\/json&#39;,\n    &#39;Content-Type&#39;: &#39;application\/json&#39;\n  };\n\n  \/\/ \u5229\u7528\u53ef\u80fd\u306a\u9077\u79fb\u4e00\u89a7\u3092\u53d6\u5f97\n  const listRes = UrlFetchApp.fetch(url, {\n    method: &#39;get&#39;,\n    headers: headers,\n    muteHttpExceptions: true\n  });\n\n  const listCode = listRes.getResponseCode();\n  const listBody = listRes.getContentText();\n\n  if (listCode &lt; 200 || listCode &gt;= 300) {\n    Logger.log(&#39;\u30b9\u30c6\u30fc\u30bf\u30b9\u53d6\u5f97\u5931\u6557 issue=&#39; + issueKey +\n               &#39; code=&#39; + listCode + &#39; body=&#39; + listBody);\n    return;\n  }\n\n  const listJson = JSON.parse(listBody);\n  const transitions = listJson.transitions || [];\n\n  \/\/ UI\u4e0a\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u540d\uff08t.to.name\uff09\u3067\u4e00\u81f4\u3092\u63a2\u3059\n  const trans = transitions.find(t =&gt;\n    t.to && t.to.name === targetStatusName\n  ) || transitions.find(t =&gt;\n    t.name === targetStatusName\n  );\n\n  if (!trans) {\n    Logger.log(&#39;\u30b9\u30c6\u30fc\u30bf\u30b9 &quot;&#39; + targetStatusName +\n               &#39;&quot; \u3078\u306e\u9077\u79fb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\uff08issue=&#39; + issueKey + &#39;\uff09&#39;);\n    return;\n  }\n\n  const payload = {\n    transition: { id: trans.id }\n  };\n\n  const doRes = UrlFetchApp.fetch(url, {\n    method: &#39;post&#39;,\n    headers: headers,\n    payload: JSON.stringify(payload),\n    muteHttpExceptions: true\n  });\n\n  const doCode = doRes.getResponseCode();\n  const doBody = doRes.getContentText();\n  if (doCode &gt;= 200 && doCode &lt; 300) {\n    Logger.log(&#39;\u30b9\u30c6\u30fc\u30bf\u30b9\u5909\u66f4\u6210\u529f issue=&#39; + issueKey +\n               &#39; -&gt; &#39; + targetStatusName);\n  } else {\n    Logger.log(&#39;\u30b9\u30c6\u30fc\u30bf\u30b9\u5909\u66f4\u5931\u6557 issue=&#39; + issueKey +\n               &#39; code=&#39; + doCode + &#39; body=&#39; + doBody);\n  }\n}\n\n\n\/* ========================\n   Jira Issue\u4f5c\u6210\n======================== *\/\n\nfunction createJiraIssue(summary, descriptionText, epicKey,\n                         assigneeRaw, priorityName, statusName) {\n  const config = getJiraConfig();\n  const projectKey = epicKey ? String(epicKey).split(&#39;-&#39;)[0] : &#39;MFLP&#39;;\n\n  const fields = {\n    project:   { key: projectKey },\n    summary:   summary,\n    issuetype: { name: &#39;Task&#39; },\n    description: {\n      type: &#39;doc&#39;,\n      version: 1,\n      content: [{\n        type: &#39;paragraph&#39;,\n        content: descriptionText\n          ? [{ type: &#39;text&#39;, text: String(descriptionText) }]\n          : []\n      }]\n    }\n  };\n\n  \/\/ \u89aa\u30a8\u30d4\u30c3\u30af\n  if (epicKey) fields.parent = { key: epicKey };\n\n  \/\/ \u62c5\u5f53\u8005\n  if (assigneeRaw) {\n    const id = findAccountIdByExactDisplayName_(assigneeRaw);\n    if (id) {\n      fields.assignee = { accountId: id };\n    } else {\n      Logger.log(&#39;WARN: \u62c5\u5f53\u8005 &quot;%s&quot; \u306e accountId \u304c\u898b\u3064\u304b\u3089\u305a\u672a\u5272\u5f53&#39;, assigneeRaw);\n    }\n  }\n\n  \/\/ \u512a\u5148\u5ea6\n  if (priorityName) {\n    fields.priority = { name: priorityName };\n  }\n\n  \/\/ Issue\u4f5c\u6210\n  const createRes = UrlFetchApp.fetch(config.baseUrl + &#39;\/rest\/api\/3\/issue&#39;, {\n    method: &#39;post&#39;,\n    headers: {\n      Authorization: &#39;Basic &#39; +\n        Utilities.base64Encode(config.email + &#39;:&#39; + config.apiToken),\n      &#39;Content-Type&#39;: &#39;application\/json&#39;,\n      Accept: &#39;application\/json&#39;\n    },\n    payload: JSON.stringify({ fields }),\n    muteHttpExceptions: true\n  });\n\n  const createCode = createRes.getResponseCode();\n  const createBody = createRes.getContentText();\n\n  if (createCode &lt; 200 || createCode &gt;= 300) {\n    Logger.log(&#39;Jira Issue\u4f5c\u6210\u30a8\u30e9\u30fc code=&#39; + createCode + &#39; body=&#39; + createBody);\n    throw new Error(&#39;Issue\u4f5c\u6210\u5931\u6557&#39;);\n  }\n\n  const issueKey = JSON.parse(createBody).key;\n  Logger.log(&#39;Issue\u4f5c\u6210\u6210\u529f: &#39; + issueKey);\n\n  \/\/ \u30b9\u30c6\u30fc\u30bf\u30b9\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u308c\u3070\u9077\u79fb\n  if (statusName) {\n    transitionIssueStatus(issueKey, statusName);\n  }\n\n  return issueKey;\n}\n\n\n\/* ========================\n   \u5b9f\u884c\u672c\u4f53\n======================== *\/\n\nfunction publishJiraTasksFromSheet() {\n  const sheet   = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(&#39;\u30b7\u30fc\u30c81&#39;);\n  const lastRow = sheet.getLastRow();\n\n  for (let r = 2; r &lt;= lastRow; r++) {\n    const \u767a\u884c\u72b6\u614b = sheet.getRange(r, 1).getValue();\n    if (\u767a\u884c\u72b6\u614b === &#39;\u6e08&#39;) continue;\n\n    const \u89aa         = sheet.getRange(r, 2).getValue(); \/\/ B: \u89aa\u30a8\u30d4\u30c3\u30af\n    const \u30bf\u30b9\u30af\u540d   = sheet.getRange(r, 5).getValue(); \/\/ E: \u30bf\u30b9\u30af\u540d\n    if (!\u30bf\u30b9\u30af\u540d) continue;\n\n    const \u62c5\u5f53\u8005     = sheet.getRange(r, 6).getValue(); \/\/ F\n    const \u30b9\u30c6\u30fc\u30bf\u30b9 = sheet.getRange(r, 7).getValue(); \/\/ G\n    const \u512a\u5148\u5ea6     = sheet.getRange(r, 8).getValue(); \/\/ H\n    const \u8aac\u660e       = sheet.getRange(r, 9).getValue(); \/\/ I: \u8aac\u660e\n\n    try {\n      const issueKey = createJiraIssue(\n        \u30bf\u30b9\u30af\u540d, \u8aac\u660e, \u89aa,\n        \u62c5\u5f53\u8005, \u512a\u5148\u5ea6, \u30b9\u30c6\u30fc\u30bf\u30b9\n      );\n\n      \/\/ A\u5217: \u767a\u884c\u6e08\u306b\n      sheet.getRange(r, 1).setValue(&#39;\u6e08&#39;);\n\n      \/\/ B\u5217: \u89aa\u30a8\u30d4\u30c3\u30af\u3092\u30ea\u30f3\u30af\u5316\uff08\u5143\u306e\u5024\u304c\u30ad\u30fc\u524d\u63d0\uff09\n      if (\u89aa) setJiraLinkToCell_(sheet, r, 2, \u89aa);\n\n      \/\/ C\u5217: \u30bf\u30b9\u30af\u30ad\u30fc\u3092\u30ea\u30f3\u30af\u5316\n      setJiraLinkToCell_(sheet, r, 3, issueKey);\n\n    } catch (e) {\n      Logger.log(&#39;\u884c &#39; + r + &#39; \u30a8\u30e9\u30fc: &#39; + e.message);\n    }\n  }\n}\n<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u51e6\u7406\u304c\u5b8c\u4e86\u3059\u308b\u3068\u3001Jira\u4e0a\u306b\u6307\u5b9a\u3057\u305f\u5185\u5bb9\u3067\u30bf\u30b9\u30af\u304c\u767b\u9332\u3055\u308c\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"623\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-1024x623.png\" alt=\"\u30b9\u30af\u30ea\u30d7\u30c8\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u3001Jira\u4e0a\u306b\u30bf\u30b9\u30af\u304c\u767b\u9332\u3055\u308c\u305f\u5f8c\u306e\u753b\u9762\u3002\" class=\"wp-image-22955\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-1024x623.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-300x183.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39-768x467.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_39.png 1264w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u884c\u5b8c\u4e86\u5f8c\u306e\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"254\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-1024x254.png\" alt=\"\u30bf\u30b9\u30af\u767b\u9332\u306e\u5b9f\u884c\u304c\u5b8c\u4e86\u3057\u305f\u5f8c\u306eGoogle\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u753b\u9762\u3002\" class=\"wp-image-22950\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-1024x254.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-300x74.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59-768x191.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_19h15_59.png 1140w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\u5fdc\u7528\uff1a\u8aac\u660e\u6b04\u306b\u753b\u50cf\u3092\u6dfb\u4ed8\u30fb\u633f\u5165\u3059\u308b\u65b9\u6cd5<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">J\u5217\u306e\u30bb\u30eb\u5185\u306b\u914d\u7f6e\u3057\u305f\u753b\u50cf\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u307f\u3001Jira\u30bf\u30b9\u30af\u306e\u8aac\u660e\u30d5\u30a3\u30fc\u30eb\u30c9\u3078\u57cb\u3081\u8fbc\u3093\u3067\u767b\u9332\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"186\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_28-1024x186.png\" alt=\"J\u5217\u306e\u30bb\u30eb\u5185\u306b\u753b\u50cf\u30c7\u30fc\u30bf\u3092\u914d\u7f6e\u3057\u305fGoogle\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u753b\u9762\u3002\" class=\"wp-image-22961\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_28-1024x186.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_28-300x54.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_28-768x139.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_28.png 1374w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"605\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-1024x605.png\" alt=\"\u30a8\u30d4\u30c3\u30af\u7d10\u4ed8\u3051\u3084\u62c5\u5f53\u8005\u5272\u308a\u5f53\u3066\u3092\u884c\u3046Jira\u30bf\u30b9\u30af\u767a\u884c\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u30b3\u30fc\u30c9\u5185\u5bb9\u3002\" class=\"wp-image-22962\" srcset=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-1024x605.png 1024w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-300x177.png 300w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48-768x454.png 768w, https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/2025-11-21_21h51_48.png 1399w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-js\" data-lang=\"JavaScript\"><code>\/************************************************\n * Jira \u30bf\u30b9\u30af\u767a\u884c\u30b9\u30af\u30ea\u30d7\u30c8\uff08\u30ea\u30d5\u30a1\u30af\u30bf\u7248\uff09\n *\n * \u6a5f\u80fd:\n *  - \u30a8\u30d4\u30c3\u30af\u7d10\u4ed8\u3051\uff08B\u5217\u306e\u30ad\u30fc\u3092 parent \u306b\u8a2d\u5b9a\uff09\n *  - \u62c5\u5f53\u8005\uff08\u8868\u793a\u540d \u2192 accountId\uff09\u3092\u5272\u308a\u5f53\u3066\n *  - \u30b9\u30c6\u30fc\u30bf\u30b9\u9077\u79fb\uff08G\u5217: To Do \/ \u9032\u884c\u4e2d \/ \u30ec\u30d3\u30e5\u30fc\u4e2d \/ \u5b8c\u4e86\uff09\n *  - \u512a\u5148\u5ea6\u8a2d\u5b9a\uff08H\u5217: Highest \/ High \/ Medium \/ Low \/ Lowest\uff09\n *  - \u8aac\u660e\uff08I\u5217\u30c6\u30ad\u30b9\u30c8\uff09+ \u672b\u5c3e\u306b\u753b\u50cf\uff08J\u5217\u30bb\u30eb\u5185\u753b\u50cf\uff09\u3092 inline \u57cb\u3081\u8fbc\u307f\n *  - B\/C\u5217\u3092 \/browse\/\u30ad\u30fc \u306e\u30cf\u30a4\u30d1\u30fc\u30ea\u30f3\u30af\u306b\u66f4\u65b0\n *\n * \u30b7\u30fc\u30c8\u69cb\u6210\uff08\u30b7\u30fc\u30c81\uff09\n *   A: \u767a\u884c\u72b6\u614b   \uff08\u7a7a \/ \u6e08\uff09\n *   B: \u89aa         \uff08\u30a8\u30d4\u30c3\u30af\u30ad\u30fc: \u4f8b MFLP-2\uff09\n *   C: \u30bf\u30b9\u30af\u756a\u53f7\uff08Jira Issue\u30ad\u30fc\uff09\n *   D: \u5831\u544a\u8005     \uff08\u672a\u4f7f\u7528\uff09\n *   E: \u30bf\u30b9\u30af\u540d   \uff08summary\uff09\n *   F: \u62c5\u5f53\u8005     \uff08Jira\u306e\u8868\u793a\u540d: \u4f8b suimin\uff09\n *   G: \u30b9\u30c6\u30fc\u30bf\u30b9 \uff08To Do \/ \u9032\u884c\u4e2d \/ \u30ec\u30d3\u30e5\u30fc\u4e2d \/ \u5b8c\u4e86\uff09\n *   H: \u512a\u5148\u5ea6     \uff08Highest \/ High \/ Medium \/ Low \/ Lowest\uff09\n *   I: \u8aac\u660e       \uff08\u30c6\u30ad\u30b9\u30c8\uff09\n *   J: \u753b\u50cf       \uff08\u30bb\u30eb\u5185\u753b\u50cf or =IMAGE()\uff09\n ************************************************\/\n\n\/\/ \u521d\u671f\u30b9\u30c6\u30fc\u30bf\u30b9\u540d\uff08\u3053\u308c\u306e\u3068\u304d\u306f\u9077\u79fb\u3057\u306a\u3044\uff09\nconst JIRA_INITIAL_STATUS_NAME = &#39;To Do&#39;;\n\n\n\/* ========================\n * \u5171\u901a\u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3\n * ====================== *\/\n\n\/**\n * \u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u304b\u3089 Jira \u63a5\u7d9a\u60c5\u5831\u3092\u53d6\u5f97\n *\/\nfunction getJiraConfig() {\n  const props    = PropertiesService.getScriptProperties();\n  let   baseUrl  = props.getProperty(&#39;JIRA_BASE_URL&#39;);\n  const email    = props.getProperty(&#39;JIRA_EMAIL&#39;);\n  const apiToken = props.getProperty(&#39;JIRA_API_TOKEN&#39;);\n\n  if (!baseUrl || !email || !apiToken) {\n    throw new Error(&#39;Jira\u63a5\u7d9a\u60c5\u5831\uff08JIRA_BASE_URL \/ JIRA_EMAIL \/ JIRA_API_TOKEN\uff09\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002&#39;);\n  }\n\n  \/\/ \u672b\u5c3e\u306e \/ \u306f\u7d71\u4e00\u3057\u3066\u524a\u9664\n  baseUrl = baseUrl.replace(\/\\\/$\/, &#39;&#39;);\n\n  return { baseUrl, email, apiToken };\n}\n\n\/**\n * Basic\u8a8d\u8a3c\u30d8\u30c3\u30c0\u30fc\u6587\u5b57\u5217\u3092\u751f\u6210\n *\/\nfunction buildBasicAuth_(email, apiToken) {\n  return &#39;Basic &#39; + Utilities.base64Encode(email + &#39;:&#39; + apiToken);\n}\n\n\/**\n * \/browse\/\u30ad\u30fc \u306e\u30cf\u30a4\u30d1\u30fc\u30ea\u30f3\u30af\u3092\u30bb\u30eb\u306b\u30bb\u30c3\u30c8\n *\/\nfunction setJiraLinkToCell_(sheet, row, col, issueKey) {\n  if (!issueKey) return;\n  const config = getJiraConfig();\n  const url = config.baseUrl + &#39;\/browse\/&#39; + issueKey;\n  sheet.getRange(row, col).setFormula(\n    `=HYPERLINK(&quot;${url}&quot;,&quot;${issueKey}&quot;)`\n  );\n}\n\n\n\/* ========================\n * \u30e6\u30fc\u30b6\u30fc\u691c\u7d22\uff08\u62c5\u5f53\u8005\uff09\n * ====================== *\/\n\n\/**\n * \u8868\u793a\u540d\u304b\u3089 Jira \u306e accountId \u3092\u53d6\u5f97\uff08\u5b8c\u5168\u4e00\u81f4\uff09\n *\/\nfunction findAccountIdByExactDisplayName_(displayName) {\n  const config = getJiraConfig();\n  const url = config.baseUrl + &#39;\/rest\/api\/3\/user\/search?query=&#39; +\n              encodeURIComponent(displayName);\n\n  const res = UrlFetchApp.fetch(url, {\n    method: &#39;get&#39;,\n    headers: {\n      Authorization: buildBasicAuth_(config.email, config.apiToken)\n    },\n    muteHttpExceptions: true\n  });\n\n  const code = res.getResponseCode();\n  const body = res.getContentText();\n  if (code &gt;= 300) {\n    Logger.log(&#39;\u30e6\u30fc\u30b6\u30fc\u691c\u7d22\u30a8\u30e9\u30fc code=%s body=%s&#39;, code, body);\n    return &#39;&#39;;\n  }\n\n  const users = JSON.parse(body);\n  for (const user of users) {\n    if (user.displayName === displayName) return user.accountId;\n  }\n  return &#39;&#39;;\n}\n\n\n\/* ========================\n * \u753b\u50cf\u51e6\u7406\uff08J\u5217\u30bb\u30eb\u5185\u753b\u50cf\uff09\n * ====================== *\/\n\n\/**\n * J\u5217\u30bb\u30eb\u304b\u3089\u753b\u50cfBlob\u3092\u53d6\u5f97\uff08CellImage or =IMAGE(&quot;URL&quot;)\uff09\n *\/\nfunction getImageBlobFromCell_(cell) {\n  const v        = cell.getValue();\n  const formula  = cell.getFormula();\n  const hasGetContentUrl = v && typeof v.getContentUrl === &#39;function&#39;;\n  const valueType        = v && v.valueType;\n\n  Logger.log(\n    &#39;getImageBlobFromCell_: value=%s, valueType=%s, hasGetContentUrl=%s, formula=%s&#39;,\n    v, valueType, hasGetContentUrl, formula\n  );\n\n  \/\/ \u2460 CellImage\uff08\u30bb\u30eb\u5185\u57cb\u3081\u8fbc\u307f\u753b\u50cf\uff09\n  if (v && (valueType === SpreadsheetApp.ValueType.IMAGE || hasGetContentUrl)) {\n    try {\n      const url = v.getContentUrl && v.getContentUrl();\n      if (!url) {\n        Logger.log(&#39;CellImage: contentUrl \u304c\u7a7a\u3067\u3059&#39;);\n        return null;\n      }\n      const res = UrlFetchApp.fetch(url, {\n        headers: { Authorization: &#39;Bearer &#39; + ScriptApp.getOAuthToken() },\n        muteHttpExceptions: true\n      });\n      const code = res.getResponseCode();\n      if (code &lt; 200 || code &gt;= 300) {\n        Logger.log(\n          &#39;CellImage\u53d6\u5f97\u5931\u6557 code=%s body=%s&#39;,\n          code, res.getContentText()\n        );\n        return null;\n      }\n      const blob = res.getBlob().setName(&#39;sheet-image.png&#39;);\n      Logger.log(\n        &#39;CellImage\u53d6\u5f97\u6210\u529f size=%s type=%s&#39;,\n        blob.getBytes().length, blob.getContentType()\n      );\n      return blob;\n    } catch (e) {\n      Logger.log(&#39;CellImage\u53d6\u5f97\u4f8b\u5916: %s&#39;, e);\n      return null;\n    }\n  }\n\n  \/\/ \u2461 =IMAGE(&quot;URL&quot;) \u306b\u3082\u5bfe\u5fdc\n  if (formula && \/^=IMAGE\\(\/i.test(formula)) {\n    const m = formula.match(\/IMAGE\\(&quot;(.+?)&quot;\/i);\n    if (m && m[1]) {\n      const imageUrl = m[1];\n      Logger.log(&#39;IMAGE\u95a2\u6570\u691c\u51fa: %s&#39;, imageUrl);\n      try {\n        const res = UrlFetchApp.fetch(imageUrl, { muteHttpExceptions: true });\n        const code = res.getResponseCode();\n        if (code &gt;= 200 && code &lt; 300) {\n          const blob = res.getBlob().setName(&#39;sheet-image.png&#39;);\n          Logger.log(\n            &#39;IMAGE\u95a2\u6570\u753b\u50cf\u53d6\u5f97\u6210\u529f size=%s type=%s&#39;,\n            blob.getBytes().length, blob.getContentType()\n          );\n          return blob;\n        } else {\n          Logger.log(\n            &#39;IMAGE\u95a2\u6570\u753b\u50cf\u53d6\u5f97\u5931\u6557 code=%s body=%s&#39;,\n            code, res.getContentText()\n          );\n        }\n      } catch (e) {\n        Logger.log(&#39;IMAGE\u95a2\u6570\u753b\u50cf\u53d6\u5f97\u4f8b\u5916: %s&#39;, e);\n      }\n    }\n  }\n\n  Logger.log(&#39;\u753b\u50cf\u306a\u3057 or \u672a\u5bfe\u5fdc\u5f62\u5f0f\u306e\u30bb\u30eb\u3067\u3059&#39;);\n  return null;\n}\n\n\n\/**\n * \u6dfb\u4ed8\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9 \u2192 mediaId \u3092\u53d6\u5f97\u3057\u3066\u8fd4\u3059\n *\n * \u623b\u308a\u5024: { attachmentId, mediaId, filename } \u307e\u305f\u306f null\n *\/\nfunction uploadAttachmentAndGetMedia_(issueKey, blob) {\n  if (!blob) return null;\n\n  const config    = getJiraConfig();\n  const attachUrl = config.baseUrl +\n    &#39;\/rest\/api\/3\/issue\/&#39; + encodeURIComponent(issueKey) + &#39;\/attachments&#39;;\n\n  \/\/ 1) \u6dfb\u4ed8\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\n  const res = UrlFetchApp.fetch(attachUrl, {\n    method: &#39;post&#39;,\n    headers: {\n      Authorization: buildBasicAuth_(config.email, config.apiToken),\n      &#39;X-Atlassian-Token&#39;: &#39;no-check&#39;,\n      Accept: &#39;application\/json&#39;\n    },\n    payload: { file: blob },\n    muteHttpExceptions: true\n  });\n\n  const code = res.getResponseCode();\n  const body = res.getContentText();\n  if (code &lt; 200 || code &gt;= 300) {\n    Logger.log(\n      &#39;\u6dfb\u4ed8\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u5931\u6557 issue=%s code=%s body=%s&#39;,\n      issueKey, code, body\n    );\n    return null;\n  }\n\n  const arr = JSON.parse(body) || [];\n  const att = arr[0];\n  if (!att) {\n    Logger.log(&#39;\u6dfb\u4ed8\u30ec\u30b9\u30dd\u30f3\u30b9\u306b\u6dfb\u4ed8\u60c5\u5831\u304c\u3042\u308a\u307e\u305b\u3093 issue=%s&#39;, issueKey);\n    return null;\n  }\n\n  Logger.log(\n    &#39;\u6dfb\u4ed8\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u6210\u529f issue=%s id=%s filename=%s&#39;,\n    issueKey, att.id, att.filename\n  );\n\n  \/\/ 2) mediaId \u3092\u53d6\u5f97\u3059\u308b\n  \/\/    att.content \u4f8b: &quot;\/rest\/api\/3\/attachment\/content\/12345&quot;\n  const contentPath = att.content;\n  if (!contentPath) {\n    Logger.log(&#39;attachment.content \u304c\u7a7a\u3067\u3059 issue=%s&#39;, issueKey);\n    return null;\n  }\n\n  const contentUrl = contentPath.startsWith(&#39;http&#39;)\n    ? contentPath\n    : config.baseUrl + contentPath;\n\n  \/\/ Location \u30d8\u30c3\u30c0\u304b\u3089 \/file\/&lt;mediaId&gt;\/binary \u306e mediaId \u3092\u629c\u304f\n  const res2 = UrlFetchApp.fetch(contentUrl, {\n    method: &#39;get&#39;,\n    headers: {\n      Authorization: buildBasicAuth_(config.email, config.apiToken)\n    },\n    followRedirects: false,\n    muteHttpExceptions: true\n  });\n\n  const code2   = res2.getResponseCode();\n  const headers = res2.getHeaders();\n  const loc     = headers.Location || headers.location;\n\n  Logger.log(\n    &#39;attachment.content GET code=%s Location=%s&#39;,\n    code2, loc\n  );\n\n  if (!loc) {\n    Logger.log(&#39;Location\u30d8\u30c3\u30c0\u304c\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093 headers=%s&#39;, JSON.stringify(headers));\n    return null;\n  }\n\n  \/\/ \u4f8b: https:\/\/api.media.atlassian.com\/file\/&lt;mediaId&gt;\/binary?...\n  const m = String(loc).match(\/\\\/file\\\/([^\\\/]+)\\\/\/);\n  if (!m) {\n    Logger.log(&#39;mediaId\u62bd\u51fa\u5931\u6557 location=%s&#39;, loc);\n    return null;\n  }\n\n  const mediaId = m[1];\n  Logger.log(&#39;mediaId\u53d6\u5f97\u6210\u529f mediaId=%s&#39;, mediaId);\n\n  return {\n    attachmentId: String(att.id),\n    mediaId: mediaId,\n    filename: att.filename\n  };\n}\n\n\n\/* ========================\n * \u8aac\u660eADF\uff08\u30c6\u30ad\u30b9\u30c8 + inline\u753b\u50cf\uff09\n * ====================== *\/\n\n\/**\n * \u8aac\u660e\u30c6\u30ad\u30b9\u30c8 + mediaId \u306e\u753b\u50cf\u3092\u672b\u5c3e\u306b\u57cb\u3081\u8fbc\u3080 ADF \u3092\u751f\u6210\n *\/\nfunction buildDescriptionADF_(descriptionText, mediaId) {\n  const content = [];\n\n  \/\/ 1\u884c\u76ee\uff1a\u8aac\u660e\u30c6\u30ad\u30b9\u30c8\n  content.push({\n    type: &#39;paragraph&#39;,\n    content: descriptionText\n      ? [{ type: &#39;text&#39;, text: String(descriptionText) }]\n      : []\n  });\n\n  \/\/ 2\u884c\u76ee\uff1ainline\u753b\u50cf\n  if (mediaId) {\n    content.push({\n      type: &#39;mediaSingle&#39;,\n      attrs: {\n        layout: &#39;align-start&#39;,\n        width: 100.0\n      },\n      content: [{\n        type: &#39;media&#39;,\n        attrs: {\n          id:   mediaId, \/\/ \/file\/&lt;mediaId&gt;\/binary \u306e mediaId\n          type: &#39;file&#39;,\n          collection: &#39;&#39; \/\/ community\u306e\u4f8b\u306b\u5408\u308f\u305b\u3066\u7a7a\u306e\u307e\u307e\n        }\n      }]\n    });\n  }\n\n  const doc = {\n    type: &#39;doc&#39;,\n    version: 1,\n    content: content\n  };\n\n  Logger.log(&#39;buildDescriptionADF_ doc=%s&#39;, JSON.stringify(doc));\n  return doc;\n}\n\n\n\/* ========================\n * \u30b9\u30c6\u30fc\u30bf\u30b9\u9077\u79fb\n * ====================== *\/\n\n\/**\n * G\u5217\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u540d\u306b\u9077\u79fb\u3055\u305b\u308b\n *  - To Do \u306e\u5834\u5408\u306f\u65b0\u898f\u4f5c\u6210\u6642\u306e\u521d\u671f\u30b9\u30c6\u30fc\u30bf\u30b9\u60f3\u5b9a\u306a\u306e\u3067\u4f55\u3082\u3057\u306a\u3044\n *\/\nfunction transitionIssueStatus(issueKey, targetStatusName) {\n  if (!targetStatusName || targetStatusName === JIRA_INITIAL_STATUS_NAME) return;\n\n  const config = getJiraConfig();\n  const url = config.baseUrl + &#39;\/rest\/api\/3\/issue\/&#39; +\n              encodeURIComponent(issueKey) + &#39;\/transitions&#39;;\n\n  const headers = {\n    Authorization: buildBasicAuth_(config.email, config.apiToken),\n    Accept: &#39;application\/json&#39;,\n    &#39;Content-Type&#39;: &#39;application\/json&#39;\n  };\n\n  \/\/ \u5229\u7528\u53ef\u80fd\u306a\u9077\u79fb\u4e00\u89a7\u53d6\u5f97\n  const listRes = UrlFetchApp.fetch(url, {\n    method: &#39;get&#39;,\n    headers: headers,\n    muteHttpExceptions: true\n  });\n\n  const listCode = listRes.getResponseCode();\n  const listBody = listRes.getContentText();\n  if (listCode &lt; 200 || listCode &gt;= 300) {\n    Logger.log(\n      &#39;\u30b9\u30c6\u30fc\u30bf\u30b9\u53d6\u5f97\u5931\u6557 issue=%s code=%s body=%s&#39;,\n      issueKey, listCode, listBody\n    );\n    return;\n  }\n\n  const listJson    = JSON.parse(listBody);\n  const transitions = listJson.transitions || [];\n\n  \/\/ t.to.name\uff08UI\u8868\u793a\u540d\uff09\u3067\u30de\u30c3\u30c1\u3002\u306a\u3051\u308c\u3070 t.name \u3082\u898b\u308b\n  const trans = transitions.find(t =&gt;\n    t.to && t.to.name === targetStatusName\n  ) || transitions.find(t =&gt;\n    t.name === targetStatusName\n  );\n\n  if (!trans) {\n    Logger.log(\n      &#39;\u30b9\u30c6\u30fc\u30bf\u30b9 &quot;%s&quot; \u3078\u306e\u9077\u79fb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 issue=%s&#39;,\n      targetStatusName, issueKey\n    );\n    return;\n  }\n\n  const payload = { transition: { id: trans.id } };\n\n  const doRes = UrlFetchApp.fetch(url, {\n    method: &#39;post&#39;,\n    headers: headers,\n    payload: JSON.stringify(payload),\n    muteHttpExceptions: true\n  });\n\n  const doCode = doRes.getResponseCode();\n  const doBody = doRes.getContentText();\n  if (doCode &gt;= 200 && doCode &lt; 300) {\n    Logger.log(\n      &#39;\u30b9\u30c6\u30fc\u30bf\u30b9\u5909\u66f4\u6210\u529f issue=%s -&gt; %s&#39;,\n      issueKey, targetStatusName\n    );\n  } else {\n    Logger.log(\n      &#39;\u30b9\u30c6\u30fc\u30bf\u30b9\u5909\u66f4\u5931\u6557 issue=%s code=%s body=%s&#39;,\n      issueKey, doCode, doBody\n    );\n  }\n}\n\n\n\/* ========================\n * Jira Issue \u4f5c\u6210\n * ====================== *\/\n\n\/**\n * Jira \u306b\u30bf\u30b9\u30af\u3092\u4f5c\u6210\u3057\u3001\u5fc5\u8981\u306a\u3089\u8aac\u660e\u3092\u300c\u30c6\u30ad\u30b9\u30c8 + \u753b\u50cf\u300d\u3067\u4e0a\u66f8\u304d\n *\/\nfunction createJiraIssue(summary, descriptionText, epicKey,\n                         assigneeRaw, priorityName, statusName,\n                         imageBlob) {\n  const config = getJiraConfig();\n  const projectKey = epicKey ? String(epicKey).split(&#39;-&#39;)[0] : &#39;MFLP&#39;;\n\n  \/\/ \u307e\u305a\u306f\u30c6\u30ad\u30b9\u30c8\u3060\u3051\u306e description \u3067 Issue \u3092\u4f5c\u6210\n  const fields = {\n    project:   { key: projectKey },\n    summary:   summary,\n    issuetype: { name: &#39;Task&#39; },\n    description: {\n      type: &#39;doc&#39;,\n      version: 1,\n      content: [{\n        type: &#39;paragraph&#39;,\n        content: descriptionText\n          ? [{ type: &#39;text&#39;, text: String(descriptionText) }]\n          : []\n      }]\n    }\n  };\n\n  \/\/ \u89aa\u30a8\u30d4\u30c3\u30af\n  if (epicKey) {\n    fields.parent = { key: epicKey };\n  }\n\n  \/\/ \u62c5\u5f53\u8005\n  if (assigneeRaw) {\n    const id = findAccountIdByExactDisplayName_(assigneeRaw);\n    if (id) {\n      fields.assignee = { accountId: id };\n    } else {\n      Logger.log(&#39;WARN: \u62c5\u5f53\u8005 &quot;%s&quot; \u306e accountId \u304c\u898b\u3064\u304b\u3089\u305a\u672a\u5272\u5f53&#39;, assigneeRaw);\n    }\n  }\n\n  \/\/ \u512a\u5148\u5ea6\n  if (priorityName) {\n    fields.priority = { name: priorityName };\n  }\n\n  \/\/ Issue \u4f5c\u6210\n  const createRes = UrlFetchApp.fetch(config.baseUrl + &#39;\/rest\/api\/3\/issue&#39;, {\n    method: &#39;post&#39;,\n    headers: {\n      Authorization: buildBasicAuth_(config.email, config.apiToken),\n      &#39;Content-Type&#39;: &#39;application\/json&#39;,\n      Accept: &#39;application\/json&#39;\n    },\n    payload: JSON.stringify({ fields }),\n    muteHttpExceptions: true\n  });\n\n  const createCode = createRes.getResponseCode();\n  const createBody = createRes.getContentText();\n\n  if (createCode &lt; 200 || createCode &gt;= 300) {\n    Logger.log(&#39;Jira Issue\u4f5c\u6210\u30a8\u30e9\u30fc code=%s body=%s&#39;, createCode, createBody);\n    throw new Error(&#39;Issue\u4f5c\u6210\u5931\u6557&#39;);\n  }\n\n  const issueKey = JSON.parse(createBody).key;\n  Logger.log(&#39;Issue\u4f5c\u6210\u6210\u529f: %s&#39;, issueKey);\n\n  \/\/ \u753b\u50cf\u304c\u3042\u308c\u3070: \u6dfb\u4ed8 \u2192 mediaId \u53d6\u5f97 \u2192 description \u3092\u300c\u30c6\u30ad\u30b9\u30c8+\u753b\u50cf\u300d\u306b\u66f4\u65b0\n  if (imageBlob) {\n    const info = uploadAttachmentAndGetMedia_(issueKey, imageBlob);\n    if (info && info.mediaId) {\n      const descADF   = buildDescriptionADF_(descriptionText, info.mediaId);\n      const updateUrl = config.baseUrl + &#39;\/rest\/api\/3\/issue\/&#39; +\n                        encodeURIComponent(issueKey);\n\n      Logger.log(&#39;descADF for %s: %s&#39;, issueKey, JSON.stringify(descADF));\n\n      const updateRes = UrlFetchApp.fetch(updateUrl, {\n        method: &#39;put&#39;,\n        headers: {\n          Authorization: buildBasicAuth_(config.email, config.apiToken),\n          &#39;Content-Type&#39;: &#39;application\/json&#39;,\n          Accept: &#39;application\/json&#39;\n        },\n        payload: JSON.stringify({ fields: { description: descADF } }),\n        muteHttpExceptions: true\n      });\n\n      const upCode = updateRes.getResponseCode();\n      const upBody = updateRes.getContentText();\n      if (upCode &gt;= 200 && upCode &lt; 300) {\n        Logger.log(&#39;description \u66f4\u65b0\u6210\u529f issue=%s&#39;, issueKey);\n      } else {\n        Logger.log(\n          &#39;description \u66f4\u65b0\u5931\u6557 issue=%s code=%s body=%s&#39;,\n          issueKey, upCode, upBody\n        );\n      }\n    } else {\n      Logger.log(&#39;mediaId \u306a\u3057: description \u57cb\u3081\u8fbc\u307f\u30b9\u30ad\u30c3\u30d7 issue=%s&#39;, issueKey);\n    }\n  }\n\n  \/\/ \u30b9\u30c6\u30fc\u30bf\u30b9\u9077\u79fb\uff08To Do \u4ee5\u5916\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\uff09\n  if (statusName) {\n    transitionIssueStatus(issueKey, statusName);\n  }\n\n  return issueKey;\n}\n\n\n\/* ========================\n * \u5b9f\u884c\u672c\u4f53\n * ====================== *\/\n\n\/**\n * \u30b7\u30fc\u30c81\u306e\u884c\u3092\u8d70\u67fb\u3057\u3066 Jira Issue \u3092\u767a\u884c\n *  - A\u5217\u304c\u300c\u6e08\u300d\u306e\u884c\u306f\u30b9\u30ad\u30c3\u30d7\n *  - E\u5217\uff08\u30bf\u30b9\u30af\u540d\uff09\u304c\u7a7a\u306e\u884c\u3082\u30b9\u30ad\u30c3\u30d7\n *  - \u6210\u529f\u3057\u305f\u884c\u306f A\u5217=\u6e08 \/ B,C\u5217\u30ea\u30f3\u30af\u5316\n *\/\nfunction publishJiraTasksFromSheet() {\n  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(&#39;\u30b7\u30fc\u30c81&#39;);\n  const lastRow = sheet.getLastRow();\n  if (!sheet || lastRow &lt; 2) {\n    Logger.log(&#39;\u5bfe\u8c61\u30c7\u30fc\u30bf\u884c\u304c\u3042\u308a\u307e\u305b\u3093&#39;);\n    return;\n  }\n\n  for (let r = 2; r &lt;= lastRow; r++) {\n    const \u767a\u884c\u72b6\u614b = sheet.getRange(r,1).getValue();\n    if (\u767a\u884c\u72b6\u614b === &#39;\u6e08&#39;) continue;\n\n    const \u89aa       = sheet.getRange(r,2).getValue();  \/\/ B: \u89aa\u30a8\u30d4\u30c3\u30af\n    const \u30bf\u30b9\u30af\u540d = sheet.getRange(r,5).getValue();  \/\/ E: \u30bf\u30b9\u30af\u540d\n    if (!\u30bf\u30b9\u30af\u540d) continue;\n\n    const \u62c5\u5f53\u8005     = sheet.getRange(r,6).getValue();  \/\/ F\n    const \u30b9\u30c6\u30fc\u30bf\u30b9 = sheet.getRange(r,7).getValue();  \/\/ G\n    const \u512a\u5148\u5ea6     = sheet.getRange(r,8).getValue();  \/\/ H\n    const \u8aac\u660e       = sheet.getRange(r,9).getValue();  \/\/ I: \u8aac\u660e\n    const imageBlob  = getImageBlobFromCell_(sheet.getRange(r,10)); \/\/ J: \u753b\u50cf\n\n    try {\n      const issueKey = createJiraIssue(\n        \u30bf\u30b9\u30af\u540d, \u8aac\u660e, \u89aa,\n        \u62c5\u5f53\u8005, \u512a\u5148\u5ea6, \u30b9\u30c6\u30fc\u30bf\u30b9, imageBlob\n      );\n\n      \/\/ A\u5217: \u767a\u884c\u6e08\n      sheet.getRange(r,1).setValue(&#39;\u6e08&#39;);\n\n      \/\/ B\u5217: \u89aa\u30a8\u30d4\u30c3\u30af\u30ea\u30f3\u30af\n      if (\u89aa) setJiraLinkToCell_(sheet, r, 2, \u89aa);\n\n      \/\/ C\u5217: \u30bf\u30b9\u30af\u30ea\u30f3\u30af\n      setJiraLinkToCell_(sheet, r, 3, issueKey);\n\n    } catch (e) {\n      Logger.log(&#39;\u884c %s \u3067\u30a8\u30e9\u30fc: %s&#39;, r, e.message);\n      \/\/ A\u5217\u306f\u7a7a\u306e\u307e\u307e\u306b\u3057\u3066\u3001\u5f8c\u3067\u518d\u5b9f\u884c\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\n    }\n  }\n}\n<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u306e\u8a18\u4e8b\u3067\u7d39\u4ecb\u3057\u3066\u3044\u308b\u30b3\u30fc\u30c9\u306f\u3001GitHub\u306e<a href=\"https:\/\/github.com\/MOTOKI-LLC\/cg-method-code\/tree\/main\/google\/google-spreadsheet-to-jira-task\">MOTOKI-LLC\/cg-method-code<\/a>\u306b\u3082\u307e\u3068\u3081\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n<!-- cgm-topic:start -->\n\n\n<p class=\"wp-block-paragraph\">\u5916\u90e8\u306e\u30b5\u30fc\u30d3\u30b9\u3068\u9023\u643a\u3059\u308b\u8a18\u4e8b\u306f\u3001\u307b\u304b\u306b\u3082\u3042\u308a\u307e\u3059\u3002<\/p>\n\n\n<div class=\"swell-block-postLink\">\t\t\t<div class=\"p-blogCard -internal\" data-type=\"type1\" data-onclick=\"clickLink\">\n\t\t\t\t<div class=\"p-blogCard__inner\">\n\t\t\t\t\t<span class=\"p-blogCard__caption\">\u3042\u308f\u305b\u3066\u8aad\u307f\u305f\u3044<\/span>\n\t\t\t\t\t<div class=\"p-blogCard__thumb c-postThumb\"><figure class=\"c-postThumb__figure\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/google-spreadsheet-jira-task-export-gas-300x169.jpg\" alt=\"\" class=\"c-postThumb__img u-obf-cover\" width=\"320\" height=\"180\"><\/figure><\/div>\t\t\t\t\t<div class=\"p-blogCard__body\">\n\t\t\t\t\t\t<a class=\"p-blogCard__title\" href=\"https:\/\/cg-method.com\/google\/google-spreadsheet-jira-task-export-gas\/\">Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u2502JIRA\u306e\u30bf\u30b9\u30af\u3092\u30b7\u30fc\u30c8\u306b\u51fa\u529b\u3059\u308b\u65b9\u6cd5<\/a>\n\t\t\t\t\t\t<span class=\"p-blogCard__excerpt\">Jira\u306e\u30a8\u30d4\u30c3\u30af\u3092\u6307\u5b9a\u3057\u3001\u8a72\u5f53\u3059\u308b\u30bf\u30b9\u30af\u3092Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u3078\u51fa\u529b\u3059\u308b\u624b\u9806\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002 \u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u8a2d\u5b9a \u524d\u63d0\u3068\u3057\u3066\u3001Jira\u306eAPI\u30c8\u30fc\u30af\u30f3\u306a\u3069\u3092\u4e8b\u524d&#8230;<\/span>\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\n<div class=\"swell-block-postLink\">\t\t\t<div class=\"p-blogCard -internal\" data-type=\"type1\" data-onclick=\"clickLink\">\n\t\t\t\t<div class=\"p-blogCard__inner\">\n\t\t\t\t\t<span class=\"p-blogCard__caption\">\u3042\u308f\u305b\u3066\u8aad\u307f\u305f\u3044<\/span>\n\t\t\t\t\t<div class=\"p-blogCard__thumb c-postThumb\"><figure class=\"c-postThumb__figure\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/11\/gemini-api-spreadsheet-gas-free-300x169.jpg\" alt=\"\" class=\"c-postThumb__img u-obf-cover\" width=\"320\" height=\"180\"><\/figure><\/div>\t\t\t\t\t<div class=\"p-blogCard__body\">\n\t\t\t\t\t\t<a class=\"p-blogCard__title\" href=\"https:\/\/cg-method.com\/google\/gemini-api-spreadsheet-gas-free\/\">Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u2502Gemini API\u306e\u7121\u6599\u67a0\u3092\u4f7f\u3046\u65b9\u6cd5<\/a>\n\t\t\t\t\t\t<span class=\"p-blogCard__excerpt\">\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u6a19\u6e96AI\u6a5f\u80fd\u3060\u3051\u3067\u306f\u5bfe\u5fdc\u3057\u306b\u304f\u3044\u51e6\u7406\u304c\u3042\u308a\u3001 \u5927\u91cf\u306e\u30c7\u30fc\u30bf\u3092\u307e\u3068\u3081\u3066\u51e6\u7406\u3059\u308b\u305f\u3081\u306bGemini API\u306e\u7121\u6599\u67a0\u3092\u6d3b\u7528\u3059\u308b\u624b\u9806\u3092\u691c\u8a3c\u3057\u307e\u3057\u305f\u3002 Google\u30b9\u30d7&#8230;<\/span>\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\n<div class=\"swell-block-postLink\">\t\t\t<div class=\"p-blogCard -internal\" data-type=\"type1\" data-onclick=\"clickLink\">\n\t\t\t\t<div class=\"p-blogCard__inner\">\n\t\t\t\t\t<span class=\"p-blogCard__caption\">\u3042\u308f\u305b\u3066\u8aad\u307f\u305f\u3044<\/span>\n\t\t\t\t\t<div class=\"p-blogCard__thumb c-postThumb\"><figure class=\"c-postThumb__figure\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/05\/gas-chatgpt-300x169.jpg\" alt=\"\" class=\"c-postThumb__img u-obf-cover\" width=\"320\" height=\"180\"><\/figure><\/div>\t\t\t\t\t<div class=\"p-blogCard__body\">\n\t\t\t\t\t\t<a class=\"p-blogCard__title\" href=\"https:\/\/cg-method.com\/google\/gas-chatgpt\/\">GAS\u2502Google Apps Script\u3067\u4f5c\u308b\uff01ChatGPT\u98a8\u30c1\u30e3\u30c3\u30c8\u30dc\u30c3\u30c8\u306e\u4f5c\u308a\u65b9\u5165\u9580<\/a>\n\t\t\t\t\t\t<span class=\"p-blogCard__excerpt\">ChatGPT\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u306a\u3044\u74b0\u5883\u3084\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6301\u3063\u3066\u3044\u306a\u3044\u4eba\u306bChatGPT\u3092\u4f7f\u3063\u3066\u3082\u3089\u3046\u306b\u306f\u3069\u3046\u3057\u305f\u3089\u3088\u3044\u3067\u3057\u3087\u3046\u304b\u3002 ChatGPT\u306eAPI\u3092\u6d3b\u7528\u3057\u3001GAS\uff08Google Apps Scrip&#8230;<\/span>\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\n<div class=\"swell-block-postLink\">\t\t\t<div class=\"p-blogCard -internal\" data-type=\"type1\" data-onclick=\"clickLink\">\n\t\t\t\t<div class=\"p-blogCard__inner\">\n\t\t\t\t\t<span class=\"p-blogCard__caption\">\u3042\u308f\u305b\u3066\u8aad\u307f\u305f\u3044<\/span>\n\t\t\t\t\t<div class=\"p-blogCard__thumb c-postThumb\"><figure class=\"c-postThumb__figure\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cg-method.com\/google\/wp-content\/uploads\/2025\/05\/google-sheets-natural-language-api-300x169.jpg\" alt=\"\" class=\"c-postThumb__img u-obf-cover\" width=\"320\" height=\"180\"><\/figure><\/div>\t\t\t\t\t<div class=\"p-blogCard__body\">\n\t\t\t\t\t\t<a class=\"p-blogCard__title\" href=\"https:\/\/cg-method.com\/google\/gcp-natural-language-api\/\">Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u2502Natural Language API\u3067\u611f\u60c5\u5206\u6790\u3092\u3059\u308b\u65b9\u6cd5\u2502GCP<\/a>\n\t\t\t\t\t\t<span class=\"p-blogCard__excerpt\">\u30c6\u30ad\u30b9\u30c8\u304c\u30dd\u30b8\u30c6\u30a3\u30d6\u304b\u30cd\u30ac\u30c6\u30a3\u30d6\u304b\u3001\u3069\u306e\u7a0b\u5ea6\u306e\u611f\u60c5\u306e\u5f37\u3055\u304c\u3042\u308b\u304b\u3092\u5224\u5b9a\u3057\u305f\u3044\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u3059\u3002 Google Cloud Platform\uff08GCP\uff09\u306e\u6a5f\u68b0\u5b66\u7fd2\u6a5f\u80fd\u3092\u5229\u7528\u3057\u3066\u611f\u60c5\u3092\u5224\u5b9a&#8230;<\/span>\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\n<!-- cgm-topic:end -->\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>Jira\u306eREST API\u3068Google Apps Script\uff08GAS\uff09\u3092\u6d3b\u7528\u3057\u3001Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u884c\u30c7\u30fc\u30bf\u304b\u3089Jira\u306e\u30bf\u30b9\u30af\u3092\u4e00\u62ec\u767b\u9332\u3059\u308b\u624b\u9806\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002 \u8ab2\u984c\u30921\u4ef6\u305a\u3064\u624b\u52d5\u767b\u9332\u305b\u305a\u3001\u30b7\u30fc\u30c8\u4e0a\u3067\u30ea\u30b9\u30c8 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":22964,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"swell_btn_cv_data":"","book_review_data":"","footnotes":"","ssp_meta_title":"Jira\u30bf\u30b9\u30af\u3092\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u304b\u3089\u4e00\u62ec\u4f5c\u6210\u3059\u308bGAS\u624b\u9806","ssp_meta_description":"Google\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8\u306e\u884c\u30c7\u30fc\u30bf\u304b\u3089Jira\u30bf\u30b9\u30af\u3092\u4e00\u62ec\u767b\u9332\u3059\u308bGAS\u306e\u624b\u9806\u3092\u89e3\u8aac\u3002\u4e8b\u524d\u6e96\u5099\u3068\u3057\u3066\u5fc5\u8981\u306aURL\u3084API\u30c8\u30fc\u30af\u30f3\u306a\u30693\u3064\u306e\u60c5\u5831\u78ba\u8a8d\u304b\u3089\u3001\u30b9\u30af\u30ea\u30d7\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u8a2d\u5b9a\u3001\u30b7\u30fc\u30c8\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u4f5c\u6210\u3068\u5b9f\u884c\u65b9\u6cd5\u307e\u3067\u8aad\u3081\u307e\u3059\u3002"},"categories":[17],"tags":[18],"class_list":["post-22945","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spreadsheets","tag-gas"],"_links":{"self":[{"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/posts\/22945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/comments?post=22945"}],"version-history":[{"count":20,"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/posts\/22945\/revisions"}],"predecessor-version":[{"id":23428,"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/posts\/22945\/revisions\/23428"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/media\/22964"}],"wp:attachment":[{"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/media?parent=22945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/categories?post=22945"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cg-method.com\/google\/wp-json\/wp\/v2\/tags?post=22945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}