質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

Q&A

解決済

1回答

2885閲覧

スプレッドシート上でGoogle Apps Script(GAS)を動かして条件に応じて転記をしたい。同じ名称はまとめて転記をしたい。

Miyabi_Kanda

総合スコア9

Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

1グッド

0クリップ

投稿2018/08/07 04:54

編集2018/08/08 02:37

前提・実現したいこと

スプレッドシート上でGoogle Apps Script(GAS)を動かして条件に応じて転記をしたい。
転記をする際に同じ名称のものは同じシートに転記したい。

###条件

顧客名と商品名が羅列されたスプレッドシートAから、
請求書を発行するGASを作っています。

ifで条件をかけて、発行するものと、しないもので分けて1シート1行で転記をすることはできました。
しかし、同一名称のもの(下記A名前が同一のもの)は請求書の明細に羅列して転記をすることができません。

スプレッドシートAは以下のようになってます。(説明のため簡略化してます)

[シートA]
┌----------┬----------┬----------┬----------┬----------┐
| A名前 |B郵便番号 | C住所 | D商品名 | D値段 |
|〇〇〇〇〇 |△△△-△△|東京都… | にんじん | ¥100 |
├----------┼----------┼----------┼----------┼----------┤
|〇〇〇〇〇 |△△△-△△|東京都… |じゃがいも | ¥80 |
├----------┼----------┼----------┼----------┼----------┤
|〇〇〇〇〇 |△△△-△△|東京都… |さつまいも | ¥150 |
├----------┼----------┼----------┼----------┼----------┤

ここの名前の部分が同一のものを、転記をするときに明細のように下側に羅列をしたいです。
よろしくお願いします。

[シートB]

郵便番号 △△△-△△
住所  東京都…
名前 〇〇〇〇〇  様

商品名   単価   個数   小計
にんじん  100    1    100
じゃがいも 80     1     80
さつまいも 150    1    150

作ったGAS

GAS

1function myfunction() { 2 3/*基本設定*/ 4 var today = new Date();//現在の日付を取得 5 var tmplId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";   //テンプレートIDの定義(シートBのテンプレ) 6 var dstDirId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  //保存先IDの定義 7 8 9/*コピー処理*/ 10 var tmpl = DriveApp.getFileById(tmplId);    //テンプレートIDからデータを取得 11 var dstDir = DriveApp.getFolderById(dstDirId); //IDからフォルダーの場所を取得 12 var ss_act = SpreadsheetApp.getActiveSpreadsheet(); //アクティブなシートを取得 13 var ss_copyFrom = ss_act.getSheetByName('シートA');   //アクティブなシート内の「合算」タブ内を参照 14 var LR_ssf = ss_copyFrom.getRange('B2:B').getLastRow(); //アクティブなシート内の「合算」タブ内の最終行を取得*つもり 15 var Data =ss_copyFrom.getDataRange().getValues(); 16 var n = 1; 17 18/*格納作業*/ 19 for(var i = 0; i<= LR_ssf; i++){ 20 if(Data[i][6] === '発行'){   //条件分岐用:明細発行有無 21 22 var s_value01 = Data[i][1];  //顧客名 23 var s_value02 = Data[i][2]; //郵便番号 24 var s_value03 = Data[i][3]; //住所 25 var s_value04 = Data[i][4]; //建物名等 26 var s_value05 = Data[i][7]; //敬称 27 28 var s_value06 = Data[i][18]; //内容 29 var s_value07 = Data[i][19]; //単価 30 var s_value08 = Data[i][20]; //数量 31 var s_value09 = Data[i][21]; //合計 32 33/*データ発行処理*/ 34 var invoice = tmpl.makeCopy(s_value01,dstDir);   //指定フォルダにデータを作成し名称をB2から↓(i,2)の値とする。 35 36/*転記シート処理*/ 37 var sst = SpreadsheetApp.open(invoice);        //作成済みデータ開く 38 var t_sheets = sst.getSheets();             //sheetsの値を定義 39 var t_sheet = t_sheets[0];                //作成済みファイルは1シートしかないので0番目を取得 40 41/*代入処理*/ 42 t_sheet.getRange('B1').setValue('〒'+s_value02); //郵便番号 を代入 43 t_sheet.getRange('B2').setValue(s_value03);      //住所を代入 44 t_sheet.getRange('B3').setValue(s_value04);      //建物名等を代入 45 t_sheet.getRange('D5').setValue(s_value05);      //敬称を代入 46 t_sheet.getRange('B5').setValue(s_value01);      //送付先名称を代入 47 t_sheet.getRange('I1').setValue("001");      //請求IDを代入*ここどうしようか悩んでます。 48 49 t_sheet.getRange('I2').setValue(today); //本日を代入 50 t_sheet.getRange('C21').setValue(s_value01);     //件名を代入 51 t_sheet.getRange('B27').setValue(s_value06);     //内容を代入 52 t_sheet.getRange('F27').setValue(s_value07);     //単価を代入 53 t_sheet.getRange('H27').setValue(s_value08);     //数量を代入 54 t_sheet.getRange('I27').setValue(s_value09); //合計を代入 55 56 57 58 } 59 } 60 61} 62
KenA👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hot-lemoned

2018/08/08 00:59

合算シート?シートA? には名前「○○○○○」ごとに商品名が記載されているのでしょうか? 例えば1行目は名前:○○○○○ で商品名:にんじん、2行目は名前:○○○○○ で商品名:じゃがいも、3行目は名前:△△△△△ で商品名:にんじん とか。。。
Miyabi_Kanda

2018/08/08 02:33

わかりにくくて申し訳ありません!その認識で間違いありません!
guest

回答1

0

ベストアンサー

すいません、説明が下手なのでコードにしてみました。
修正した点、考慮した点を簡単に列記します。

  • 合算シートの最終行が取得できていなさそうだったのでgetLastRow()を使用しています
  • もともとのソースですと合算シートの行ごとにスプレッドシートを作成する流れになっていたため、

 「発行」というキーワードがあり、一番初めに取得した顧客名を基準にスプレッドシートを作成しています。
逆に言うと制限として「発行」というキーワードが複数の顧客にまたがっているとスプレッドシートは作成されません。
合算シートがどの程度のボリュームかが検討がつかなかったので、1顧客ずつ作成する流れにしてしまいました。

  • 1つの顧客情報の中に配列で内容?商品名?を格納するようにしました。
  • 1つの項目ごとにsetValue()で記載していたのを、setValues()を使用して、

 配列でまとめて記載する流れに変えました。
都度、GASにアクセスする流れは遅くなるので、なるべく一度に記載したほうがよいと思いました。

GAS

1function myfunction() { 2 Logger.log('--処理開始--'); 3 4/*基本設定*/ 5 var tmplId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";   //テンプレートIDの定義 6 var dstDirId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  //保存先IDの定義 7 8/*コピー処理*/ 9 var tmpl = DriveApp.getFileById(tmplId);    //テンプレートIDからデータを取得 10 var dstDir = DriveApp.getFolderById(dstDirId); //IDからフォルダの場所を取得 11 var ss_act = SpreadsheetApp.getActiveSpreadsheet(); //アクティブなシートを取得 12 13 var ss_copyFrom = ss_act.getSheetByName('合算');   //アクティブなシート内の「合算」タブ内を参照 14 var LR_ssf = ss_copyFrom.getLastRow(); 15 var Data =ss_copyFrom.getDataRange().getValues(); 16 var n = 1; 17 18/*格納作業*/ 19 var strage_userinfo = []; 20 for(var i=1; i<LR_ssf; i++){ 21 if(Data[i][6] === '発行'){ 22 //条件分岐用:明細発行有無 23 24 if(strage_userinfo[0] == undefined){ 25 strage_userinfo.push(Data[i][1]); //顧客名 26 strage_userinfo.push(Data[i][2]); //郵便番号 27 strage_userinfo.push(Data[i][3]); //住所 28 strage_userinfo.push(Data[i][4]); //建物名等 29 strage_userinfo.push(Data[i][7]); //敬称 30 strage_userinfo[5] = []; 31 } 32 33 var strage_data = []; 34 if(strage_userinfo[0] === Data[i][1]){ 35 strage_data.push(Data[i][18]); //内容 36 strage_data.push(Data[i][19]); //単価 37 strage_data.push(Data[i][20]); //数量 38 strage_data.push(Data[i][21]); //合計 39 } 40 strage_userinfo[5].push(strage_data); 41 } 42 } 43 //Logger.log(strage_userinfo); 44 45/*データ発行処理*/ 46 var invoice = tmpl.makeCopy(strage_userinfo[0],dstDir);   //指定フォルダにデータを作成し名称をB2から↓(i,2)の値とする。 47 48/*転記シート処理*/ 49 var sst = SpreadsheetApp.open(invoice);        //作成済みデータ開く 50 var t_sheets = sst.getSheets();             //sheetsの値を定義 51 var t_sheet = t_sheets[0];                //作成済みファイルは1シートしかないので0番目を取得 52 53 //顧客情報 54 var invoice_inforange = t_sheet.getRange('A1:I21'); 55 var invoice_infoset = invoice_inforange.getValues(); 56 57 invoice_infoset[0][1] = ('〒'+strage_userinfo[1]); //B1:郵便番号 を代入 58 invoice_infoset[1][1] = (strage_userinfo[2]); //B2:住所を代入 59 invoice_infoset[2][1] = (strage_userinfo[3]); //B3:建物名等を代入 60 invoice_infoset[4][1] = (strage_userinfo[0]); //B5:送付先名称を代入 61 invoice_infoset[4][3] = (strage_userinfo[4]); //D5:敬称を代入 62 invoice_infoset[0][8] = ("001"); //I1:請求IDを代入*ここどうしようか悩んでます。 63 invoice_infoset[20][2] = (strage_userinfo[0]); //C21:件名を代入 64 65 /* 66 var dt = new Date(); //現在の日付を取得 67 var y = dt.getFullYear(); 68 var m = ("00" + (dt.getMonth()+1)).slice(-2); 69 var d = ("00" + dt.getDate()).slice(-2); 70 var today = y + "/" + m + "/" + d; 71 */ 72 var today = new Date(); 73 invoice_infoset[1][8] = (today); //I2:本日を代入 74 75 //Logger.log(invoice_infoset); 76 77 //出力データ 78 var invoice_datarange = t_sheet.getRange(27, 2, strage_userinfo[5].length, 8); 79 var invoice_dataset = invoice_datarange.getValues(); 80 for(var t=0; t < invoice_dataset.length; t++){ 81 invoice_dataset[t][0] = (strage_userinfo[5][t][0]); //B27:内容を代入 82 invoice_dataset[t][4] = (strage_userinfo[5][t][1]); //F27:単価を代入 83 invoice_dataset[t][6] = (strage_userinfo[5][t][2]); //H27:数量を代入 84 invoice_dataset[t][7] = (strage_userinfo[5][t][3]); //I27:合計を代入 85 } 86 //Logger.log(invoice_dataset); 87 88 //顧客情報を転記シートに記入 89 invoice_inforange.setValues(invoice_infoset); 90 //出力データを転記シートに記入 91 invoice_datarange.setValues(invoice_dataset); 92 93 Logger.log('--処理終了--'); 94}

1顧客ずつスプレッドシートを作成するのではなく、
まとめて作成する場合にはさらに合算シート内でフラグを設けておいたほうがよいかと思いました。
あ… それとも月末とかにまとめて請求書発行するのであれば、別にフラグ関係なかったか…orz

いかがでしょうか?
まだ勉強中の身のため説明が下手ですいません。。。


追記(2018/08/09)

複数のスプレッドシートが作成できるようにしてみました。

格納作業のところで、顧客名ごとにデータをまとめる作業をしました。
もう少し効率のよい書き方があると思います。。。

データ発行処理のところで、顧客名ごとにスプレッドシートを作成しています。
GASに問い合わせする回数を減らすのがいずれもポイントなんだと思います。

簡単なテストしかしていないので適宜修正してください。

GAS

1function myfunction() { 2 Logger.log('--処理開始--'); 3 4/*基本設定*/ 5 var tmplId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";   //テンプレートIDの定義 6 var dstDirId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  //保存先IDの定義 7 8/*コピー処理*/ 9 var tmpl = DriveApp.getFileById(tmplId);    //テンプレートIDからデータを取得 10 var dstDir = DriveApp.getFolderById(dstDirId); //IDからフォルダの場所を取得 11 var ss_act = SpreadsheetApp.getActiveSpreadsheet(); //アクティブなシートを取得 12 13 var ss_copyFrom = ss_act.getSheetByName('合算');   //アクティブなシート内の「合算」タブ内を参照 14 var LR_ssf = ss_copyFrom.getLastRow(); 15 var Data = ss_copyFrom.getDataRange().getValues(); 16 var n = 1; 17 18 //Logger.log(Data); 19 20/*格納作業*/ 21 var strage_userinfo = []; 22 for(var i=1; i < LR_ssf; i++){ 23 if(Data[i][6] == '発行'){ 24 //条件分岐用:明細発行有無 25 if(strage_userinfo.length > 0){ 26 //配列に1つ以上顧客情報がある 27 for(var a=0; a < strage_userinfo.length; a++){ 28 var search_name = strage_userinfo[a].indexOf(Data[i][1]); 29 if(search_name >=0){ 30 //顧客名が見つかった 31 var strage_data = [ 32 Data[i][18], //内容 33 Data[i][19], //単価 34 Data[i][20], //数量 35 Data[i][21] //合計 36 ]; 37 strage_userinfo[a][5].push(strage_data); 38 break; 39 40 }else if(search_name == -1){ 41 //顧客名見つからない 42 if(a+1 == strage_userinfo.length){ 43 //配列内には顧客名なし 44 var user_array =[ 45 Data[i][1], //顧客名 46 Data[i][2], //郵便番号 47 Data[i][3], //住所 48 Data[i][4], //建物名等 49 Data[i][7], //敬称 50 [] 51 ]; 52 var strage_data = [ 53 Data[i][18], //内容 54 Data[i][19], //単価 55 Data[i][20], //数量 56 Data[i][21] //合計 57 ]; 58 user_array[5].push(strage_data); 59 strage_userinfo.push(user_array); 60 break; 61 } 62 } 63 } 64 65 }else{ 66 Logger.log("配列なし"); 67 //配列の中身が存在していない 68 var user_array =[ 69 Data[i][1], //顧客名 70 Data[i][2], //郵便番号 71 Data[i][3], //住所 72 Data[i][4], //建物名等 73 Data[i][7], //敬称 74 [] 75 ]; 76 var strage_data = [ 77 Data[i][18], //内容 78 Data[i][19], //単価 79 Data[i][20], //数量 80 Data[i][21] //合計 81 ]; 82 user_array[5].push(strage_data); 83 strage_userinfo.push(user_array); 84 } 85 } 86 } 87 //Logger.log(strage_userinfo); 88 89/*データ発行処理*/ 90 for(var v=0; v < strage_userinfo.length; v++){ 91 Logger.log("--" + (v+1) +"枚目の処理--"); 92 //スプレッドシートのコピー 93 var invoice = tmpl.makeCopy(strage_userinfo[v][0],dstDir);   //指定フォルダにデータを作成し名称をB2から↓(i,2)の値とする。 94 95 //転記シート処理 96 var sst = SpreadsheetApp.open(invoice);        //作成済みデータ開く 97 var t_sheets = sst.getSheets();             //sheetsの値を定義 98 var t_sheet = t_sheets[0];                //作成済みファイルは1シートしかないので0番目を取得 99 100 //顧客情報 101 var invoice_inforange = t_sheet.getRange('A1:I21'); 102 var invoice_infoset = invoice_inforange.getValues(); 103 104 invoice_infoset[0][1] = ('〒'+strage_userinfo[v][1]); //B1:郵便番号 を代入 105 invoice_infoset[1][1] = (strage_userinfo[v][2]); //B2:住所を代入 106 invoice_infoset[2][1] = (strage_userinfo[v][3]); //B3:建物名等を代入 107 invoice_infoset[4][1] = (strage_userinfo[v][0]); //B5:送付先名称を代入 108 invoice_infoset[4][3] = (strage_userinfo[v][4]); //D5:敬称を代入 109 invoice_infoset[0][8] = ("001"); //I1:請求IDを代入*ここどうしようか悩んでます。 110 invoice_infoset[20][2] = (strage_userinfo[v][0]); //C21:件名を代入 111 112 /* 113 var dt = new Date(); //現在の日付を取得 114 var y = dt.getFullYear(); 115 var m = ("00" + (dt.getMonth()+1)).slice(-2); 116 var d = ("00" + dt.getDate()).slice(-2); 117 var today = y + "/" + m + "/" + d; 118 */ 119 var today = new Date(); 120 invoice_infoset[1][8] = (today); //I2:本日を代入 121 122 //出力データ 123 var invoice_datarange = t_sheet.getRange(27, 2, strage_userinfo[v][5].length, 8); 124 var invoice_dataset = invoice_datarange.getValues(); 125 for(var t=0; t < invoice_dataset.length; t++){ 126 invoice_dataset[t][0] = (strage_userinfo[v][5][t][0]); //B27:内容を代入 127 invoice_dataset[t][4] = (strage_userinfo[v][5][t][1]); //F27:単価を代入 128 invoice_dataset[t][6] = (strage_userinfo[v][5][t][2]); //H27:数量を代入 129 invoice_dataset[t][7] = (strage_userinfo[v][5][t][3]); //I27:合計を代入 130 } 131 //Logger.log(invoice_dataset); 132 133 //顧客情報を転記シートに記入 134 invoice_inforange.setValues(invoice_infoset); 135 //出力データを転記シートに記入 136 invoice_datarange.setValues(invoice_dataset); 137 Logger.log("--" + (v+1) +"枚目の処理終了--"); 138 } 139 140 Logger.log('--処理終了--'); 141}

投稿2018/08/08 09:27

編集2018/08/09 11:20
hot-lemoned

総合スコア63

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Miyabi_Kanda

2018/08/09 06:15

ありがとうございます! 試してみたところ、1シートに複数の顧客が混在している状況だったのでundefinedですごい量明細ができてしまいました(笑) ただやりたかったことはほとんどできました!ありがとうございます! ちなみに複数の顧客を1つのシートに混在した状態でやるとすると、loopのところを書き換えれば行けそうですかね
Miyabi_Kanda

2018/08/09 06:22

ちなみに顧客は100を超えているのでできれば1つずつやるのは避けたいのです(汗)
hot-lemoned

2018/08/09 11:26

回答を追記しました。 注意点としては、 ・スプレッドシートの出力が100以上必要なのであればタイムオーバーが考えられますので、  時間を考慮して出力するコードに変えたほうがいいと思います。  1つのスプレッドシートを作成するので2秒程度かかっていました。 ・上記に関連しますが、出力したかを確認するフラグか列を合算シート内に追加したほうがよいと思います。  でないと、実行するごとに新しいスプレッドシートが作成されてしまいます。 という感じでしょうか。
hot-lemoned

2018/08/09 11:28

あとコード見ればわかっていると思いますが、合算シートの1行目をタイトル行としています。 格納作業で var i=1 にしていますので必要に応じて修正してください。
Miyabi_Kanda

2018/08/10 05:03

動きました!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問