ここまでの記事 プログラムの続きを書いてとりあえずの完成を目指します!
今回のソースファイル全文
今回の追加分です。それぞれ、前回作成したコードファイルに追加していきます。
「~以下に追加」となっていますが、基本どこでもOKです。
define.gsに追加
// ------------------------------------------------------------------------------------------------------- // tmpシート. // ------------------------------------------------------------------------------------------------------- var TmpDataStartX = 3; // 開始 X. var TmpDataStartY = 3; // 開始 Y. var TmpYearX = 2; // 年度 X.main.gsに追加
// ------------------------------------------------------------------------------------------------------- // エントリーポイント以下に追加. // ------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------- // 「作物決定」ボタンを押した. // ------------------------------------------------------------------------------------------------------- function PushEntry() { // シートの取得. var mngSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameMng ); var dataSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameData ); var defineSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameDefine ); if ( mngSheet === null ) { return; } if ( dataSheet === null ) { return; } if ( defineSheet === null ) { return; } // 作物名が存在するかどうかチェック. var dataID = SearchDataSheet( dataSheet ); if ( dataID === -1 ) { return; } var dataIdx = GetLastRow( mngSheet, MngListIDX ) + 1; var num, tmp; // ID. mngSheet.getRange( dataIdx, MngListIDX ).setValue( dataID ); // 作物名. mngSheet.getRange( dataIdx, MngListNameX ).setValue( dataSheet.getRange( dataID, DataNameX ).getValue() ); // 科目. mngSheet.getRange( dataIdx, MngListSubjectX ).setValue( GetDataToSubject( dataSheet, defineSheet, dataID, DefineVarietySubjectX ) ); // 作業開始. num = dataSheet.getRange( dataID, DataSowingSeedStartX ).getValue(); tmp = dataSheet.getRange( dataID, DataSowingSeedResultX ).getValue(); if ( num === 0 ) { // 種まき作業がないので定植で考える. num = dataSheet.getRange( dataID, DataPlantingStartX ).getValue(); tmp = dataSheet.getRange( dataID, DataPlantingResultX ).getValue(); mngSheet.getRange( dataIdx, MngListIsSowingSeedX ).setValue( false ); } else { mngSheet.getRange( dataIdx, MngListIsSowingSeedX ).setValue( true ); } mngSheet.getRange( dataIdx, MngListWorkStartX ).setValue( num + '月' ); // 収穫. mngSheet.getRange( dataIdx, MngListWorkEndX ).setValue( dataSheet.getRange( dataID, DataHarvestStartX ).getValue() + '月' ); // 作業終了週. mngSheet.getRange( dataIdx, MngListWorkEndWeekX ).setValue( dataSheet.getRange( dataID, DataCultivationPeriodEndX ).getValue() ); // 輪作年限BASE. mngSheet.getRange( dataIdx, MngListCropRotX ).setValue( GetDataToSubject( dataSheet, defineSheet, dataID, DefineCropRotResultX ) ); // 輪作年限残り. mngSheet.getRange( dataIdx, MngListCropRotRestX ).setValue( GetDataToSubject( dataSheet, defineSheet, dataID, DefineCropRotResultX ) ); // カラ期間. if ( dataIdx !== MngListStartY ) { // 1個前の作業終了週をget. num = mngSheet.getRange( (dataIdx - 1), MngListWorkEndWeekX ).getValue(); // 選択した作物の作業開始週と比較. if ( num < tmp ) { // カラ期間計算. num = tmp - num; } else { num = OneYearToWeeks + (tmp - num); } // カラ期間. mngSheet.getRange( dataIdx, MngListIntervalX ).setValue( num ); // 前の輪作年限を全部更新. num = num + dataSheet.getRange( dataID, DataCultivationPeriodResultX ).getValue(); // カラ期間+栽培期間(ざっくり). for ( var y = MngListStartY; y < dataIdx; ++y ) { tmp = mngSheet.getRange( y, MngListCropRotRestX ).getValue(); if ( tmp === 0 ) { continue; } tmp = tmp - num; if ( tmp < 0 ) { tmp = 0; } mngSheet.getRange( y, MngListCropRotRestX ).setValue( tmp ); } } return; } // ------------------------------------------------------------------------------------------------------- // 「スケジュール作成」ボタンを押した. // ------------------------------------------------------------------------------------------------------- function PushCreateSchedule() { // シートの取得. var mngSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameMng ); var dataSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameData ); var defineSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameDefine ); if ( mngSheet === null ) { return; } if ( dataSheet === null ) { return; } if ( defineSheet === null ) { return; } // 指定シート名が存在するか. var newSheetName = mngSheet.getRange( MngConfigSheetName ).getValue(); var newSheet = GetSheet( newSheetName ); if ( newSheet !== null ) { // シートを削除する. DeleteSheet( newSheet ); } // 新たに作成. newSheet = CopySheet( SheetNameTmp, newSheetName ); // 作物リストを頭から解釈してく. var dataEnd = GetLastRow( mngSheet, MngListIDX ) + 1; var year = 0, ID, isSeed, start, end, index = 1, col, name; // ~年目入力. DrawYear( newSheet, (year + 1) ); for ( var y = MngListStartY; y < dataEnd; ++y ) { // ID. ID = mngSheet.getRange( y, MngListIDX ).getValue(); // 種まきか否か. isSeed = mngSheet.getRange( y, MngListIsSowingSeedX ).getValue(); // 作業終了週. end = dataSheet.getRange( ID, DataCultivationPeriodEndX ).getValue(); // 色. col = GetBGColorToSubject( defineSheet, mngSheet.getRange( y, MngListSubjectX ).getValue() ); // 名前. name = mngSheet.getRange( y, MngListNameX ).getValue(); if ( isSeed === true ) { // 種まき開始週. start = dataSheet.getRange( ID, DataSowingSeedResultX ).getValue(); } else { // 定植開始週. start = dataSheet.getRange( ID, DataPlantingResultX ).getValue(); } // 色塗り開始. if ( y !== MngListStartY ) { if ( index >= start ) { // 1年ずらす. ++year; // ~年目入力. DrawYear( newSheet, (year + 1) ); } } index = start; // 名前入力. newSheet.getRange( (TmpDataStartY + year), (index + TmpDataStartX - 1) ).setValue( name ); while ( true ) { // 終了チェック. if ( index === end ) { break; } // 色塗り. newSheet.getRange( (TmpDataStartY + year), (index + TmpDataStartX - 1) ).setBackground( col ); ++index; if ( index > OneYearToWeeks ) { // 年数を増やす. ++year; // ~年目入力. DrawYear( newSheet, (year + 1) ); index = 1; } } } return; } // ------------------------------------------------------------------------------------------------------- // 「1つ消す」ボタンを押した. // ------------------------------------------------------------------------------------------------------- function PushOnePrev() { // シートの取得. var mngSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameMng ); var dataSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameData ); if ( mngSheet === null ) { return; } if ( dataSheet === null ) { return; } var endY = GetLastRow( mngSheet, MngListIDX ); if ( endY < MngListStartY ) { return; } // 消してしまうカラ期間 + 栽培期間. var baseNum, tmp; var num = mngSheet.getRange( endY, MngListIntervalX ).getValue() + dataSheet.getRange( mngSheet.getRange( endY, MngListIDX ).getValue(), DataCultivationPeriodResultX ).getValue(); RangeClear( mngSheet, MngListIDX, endY, 10, 1 ); // 輪作年限を再設定. for ( var y = MngListStartY; y < endY; ++y ) { baseNum = mngSheet.getRange( y, MngListCropRotX ).getValue(); if ( baseNum === 0 ) { continue; }// 輪作年限がもともとない作物はスキップ. tmp = mngSheet.getRange( y, MngListCropRotRestX ).getValue(); tmp = tmp + num; // base以上にならないようにする. if ( tmp > baseNum ) { tmp = baseNum; } mngSheet.getRange( y, MngListCropRotRestX ).setValue( tmp ); } return; } // ------------------------------------------------------------------------------------------------------- // 「全部消す」ボタンを押した. // ------------------------------------------------------------------------------------------------------- function PushAllDelete() { // シートの取得. var mngSheet = SpreadsheetApp.openById( SheetID ).getSheetByName( SheetNameMng ); if ( mngSheet === null ) { return; } RangeClear( mngSheet, MngListIDX, MngListStartY, 10, 0 ); return; } // ------------------------------------------------------------------------------------------------------- // private以下に追加. // ------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------- // 現在のスプレッドシートの中の指定の名前のシートを取得. // ------------------------------------------------------------------------------------------------------- function GetSheet( sheetName ) { return SpreadsheetApp.getActive().getSheetByName( sheetName ); } // ------------------------------------------------------------------------------------------------------- // スプレッドシートを削除. // ------------------------------------------------------------------------------------------------------- function DeleteSheet( sheet ) { SpreadsheetApp.getActive().deleteSheet( sheet ); return; } // ------------------------------------------------------------------------------------------------------- // スプレッドシートをコピー作成&リネーム. // ------------------------------------------------------------------------------------------------------- function CopySheet( copySheetName, newSheetName ) { var copy = GetSheet( copySheetName ); if ( copy === null ) { return null; }// 失敗. var newSheet = copy.copyTo( SpreadsheetApp.getActive() ); if ( newSheet === null ) { return null; }//失敗. // リネーム. newSheet.setName( newSheetName ); return newSheet; } // ------------------------------------------------------------------------------------------------------- // ~年目入力. // ------------------------------------------------------------------------------------------------------- function DrawYear( tmpSheet, year ) { tmpSheet.getRange( ((TmpDataStartY - 1) + year), TmpYearX ).setValue( year + '年目' ); return; } // ------------------------------------------------------------------------------------------------------- // 科目名の背景カラーを取得. // ------------------------------------------------------------------------------------------------------- function GetBGColorToSubject( defineSheet, subjectName ) { var endIdx = GetLastRow( defineSheet, DefineSubjectX ) + 1; var ranges = defineSheet.getRange( DefineDataStartY, DefineSubjectX, endIdx, 1 ).createTextFinder( subjectName ).findAll(); if ( ranges.length === 0 ) { return '#ffffff'; } return ranges[0].getBackground(); }
【解説】「作物決定」ボタンの処理実装
18~62行目
// 作物名が存在するかどうかチェック. var dataID = SearchDataSheet( dataSheet ); if ( dataID === -1 ) { return; } var dataIdx = GetLastRow( mngSheet, MngListIDX ) + 1; var num, tmp; // ID. mngSheet.getRange( dataIdx, MngListIDX ).setValue( dataID ); // 作物名. mngSheet.getRange( dataIdx, MngListNameX ).setValue( dataSheet.getRange( dataID, DataNameX ).getValue() ); // 科目. mngSheet.getRange( dataIdx, MngListSubjectX ).setValue( GetDataToSubject( dataSheet, defineSheet, dataID, DefineVarietySubjectX ) ); // 作業開始. num = dataSheet.getRange( dataID, DataSowingSeedStartX ).getValue(); tmp = dataSheet.getRange( dataID, DataSowingSeedResultX ).getValue(); if ( num === 0 ) { // 種まき作業がないので定植で考える. num = dataSheet.getRange( dataID, DataPlantingStartX ).getValue(); tmp = dataSheet.getRange( dataID, DataPlantingResultX ).getValue(); mngSheet.getRange( dataIdx, MngListIsSowingSeedX ).setValue( false ); } else { mngSheet.getRange( dataIdx, MngListIsSowingSeedX ).setValue( true ); } mngSheet.getRange( dataIdx, MngListWorkStartX ).setValue( num + '月' ); // 収穫. mngSheet.getRange( dataIdx, MngListWorkEndX ).setValue( dataSheet.getRange( dataID, DataHarvestStartX ).getValue() + '月' ); // 作業終了週. mngSheet.getRange( dataIdx, MngListWorkEndWeekX ).setValue( dataSheet.getRange( dataID, DataCultivationPeriodEndX ).getValue() ); // 輪作年限BASE. mngSheet.getRange( dataIdx, MngListCropRotX ).setValue( GetDataToSubject( dataSheet, defineSheet, dataID, DefineCropRotResultX ) ); // 輪作年限残り. mngSheet.getRange( dataIdx, MngListCropRotRestX ).setValue( GetDataToSubject( dataSheet, defineSheet, dataID, DefineCropRotResultX ) );選択中のセルの作物名から「data」シートを検索し、縦列をIDとして利用しています。
(別途IDをつけたい場合はdataシートを改造)
その後IDを使用し必要なデータを取り出しています。
64~77行目
// カラ期間. if ( dataIdx !== MngListStartY ) { // 1個前の作業終了週をget. num = mngSheet.getRange( (dataIdx - 1), MngListWorkEndWeekX ).getValue(); // 選択した作物の作業開始週と比較. if ( num < tmp ) { // カラ期間計算. num = tmp - num; } else { num = OneYearToWeeks + (tmp - num); } // カラ期間. mngSheet.getRange( dataIdx, MngListIntervalX ).setValue( num );このツールでは「カラ期間」を計算しています。
…勝手に命名してますので好きに呼んでやってください。
ここで言うカラ期間は選択した作物間の空きの期間(週数)です。
スケジュールの作成がしやすいように保持しています。
79~87行目
// 前の輪作年限を全部更新. num = num + dataSheet.getRange( dataID, DataCultivationPeriodResultX ).getValue(); // カラ期間+栽培期間(ざっくり). for ( var y = MngListStartY; y < dataIdx; ++y ) { tmp = mngSheet.getRange( y, MngListCropRotRestX ).getValue(); if ( tmp === 0 ) { continue; } tmp = tmp - num; if ( tmp < 0 ) { tmp = 0; } mngSheet.getRange( y, MngListCropRotRestX ).setValue( tmp ); }カラ期間の計算ののち、現在選択中の作物の輪作年限数の消化をしています。
コメントにも書かれていますが、(ざっくり)してます。
【解説】「スケジュール作成」ボタンの処理実装
126~179行目
for ( var y = MngListStartY; y < dataEnd; ++y ) { // ID. ID = mngSheet.getRange( y, MngListIDX ).getValue(); // 種まきか否か. isSeed = mngSheet.getRange( y, MngListIsSowingSeedX ).getValue(); // 作業終了週. end = dataSheet.getRange( ID, DataCultivationPeriodEndX ).getValue(); // 色. col = GetBGColorToSubject( defineSheet, mngSheet.getRange( y, MngListSubjectX ).getValue() ); // 名前. name = mngSheet.getRange( y, MngListNameX ).getValue(); if ( isSeed === true ) { // 種まき開始週. start = dataSheet.getRange( ID, DataSowingSeedResultX ).getValue(); } else { // 定植開始週. start = dataSheet.getRange( ID, DataPlantingResultX ).getValue(); } // 色塗り開始. if ( y !== MngListStartY ) { if ( index >= start ) { // 1年ずらす. ++year; // ~年目入力. DrawYear( newSheet, (year + 1) ); } } index = start; // 名前入力. newSheet.getRange( (TmpDataStartY + year), (index + TmpDataStartX - 1) ).setValue( name ); while ( true ) { // 終了チェック. if ( index === end ) { break; } // 色塗り. newSheet.getRange( (TmpDataStartY + year), (index + TmpDataStartX - 1) ).setBackground( col ); ++index; if ( index > OneYearToWeeks ) { // 年数を増やす. ++year; // ~年目入力. DrawYear( newSheet, (year + 1) ); index = 1; } } }このツールのキモと言っても過言ではない部分です。
作業期間部分のみを色塗りしていきます。色は「define」シートのセルの背景色から取得しています。
【解説】「1つ消す」「全部消す」ボタンの処理実装
200~223行目
// 消してしまうカラ期間 + 栽培期間. var baseNum, tmp; var num = mngSheet.getRange( endY, MngListIntervalX ).getValue() + dataSheet.getRange( mngSheet.getRange( endY, MngListIDX ).getValue(), DataCultivationPeriodResultX ).getValue(); RangeClear( mngSheet, MngListIDX, endY, 10, 1 ); // 輪作年限を再設定. for ( var y = MngListStartY; y < endY; ++y ) { baseNum = mngSheet.getRange( y, MngListCropRotX ).getValue(); if ( baseNum === 0 ) { continue; }// 輪作年限がもともとない作物はスキップ. tmp = mngSheet.getRange( y, MngListCropRotRestX ).getValue(); tmp = tmp + num; // base以上にならないようにする. if ( tmp > baseNum ) { tmp = baseNum; } mngSheet.getRange( y, MngListCropRotRestX ).setValue( tmp ); }作物リストから1つ消す場合は残り輪作年限をもとに戻さないといけません。
改善点など
ソースを見直して、軽くできそうな箇所は軽くしたいですね(;'∀')ざっくりスケジュールなので、リアルベースでツールを考えてみる?
スケジュールを作成する時の文字色も「define」シートから引っ張っても良いと思います。
…などなど、色々手を加えられそうな部分は山ほどありそうです。
これで一旦完成という事になります!長丁場お疲れ様です。
こんな感じでプログラムと農業、色々とできそうな気がして、考えるだけでワクワクしませんか?(`・ω・´)ノ
私だけか…?