
ここまでの記事 プログラムの続きを書いてとりあえずの完成を目指します!
今回のソースファイル全文
今回の追加分です。それぞれ、前回作成したコードファイルに追加していきます。
「~以下に追加」となっていますが、基本どこでも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」シートから引っ張っても良いと思います。
…などなど、色々手を加えられそうな部分は山ほどありそうです。
これで一旦完成という事になります!長丁場お疲れ様です。
こんな感じでプログラムと農業、色々とできそうな気がして、考えるだけでワクワクしませんか?(`・ω・´)ノ
私だけか…?


