There are several aspects to your question. This answer is designed to calculate the number of "unplanted days" for a given bed. You want to analyse your date by bed, though your sample date includes a single bed. Extending this answer to consider additional beds, each with their own crop plan is the next step.
The answer depends on two columns; this could probably be simplified but the purpose at this stage is to show a method for calculating the "unplanted" days.
Note: The answer also assumes that the data is sorted by Seed Date.
Latest Harvest Date
- In Cell F2, insert this formula and copy down as many rows as required
=max($E$2:E2)
: This will show the latest harvest date.
Unplanted Days
- In cell G3, insert this formula and copy down as many rows as required
=if(C3<=F2,0,C3-F2)
: This compares the crop "seed date" with the "latest harvest date" at the time of planting the previous crop. If the seed date greater than the previous "latest Harvest date", then the number of "unplanted days" equals the difference between the "seed date" and the previous "latest harvest date".

ADDENDUM#1 (23 Jan 2021)
This is a continuation of the earlier answer explaining how to calculate unplanted days.
This includes details for:
- copying "Crop Plan" to another sheet for easier analysis
- creation of help columns
- updating the formulas for "Max Harvest date" and "Unplanted days" to reflect a data source that includes multiple crop beds.
- conditional formatting
Copying "Crop Plan" to another sheet
A farmer may choose many beds and many crops, many dates. The data entry screen on Crop Plan is convenient for entering small volumes, but it doesn't lend itself to entering volumes of data, or to analysing data.
I propose that "Crop Plan" data is copied/appended to a second sheet. I called this sheet "Output" but the sheet name is a variable in the code, so you can change this to whatever you might want.
The script to copy "Crop Plan" to "Output" is:
function updateCrop2Output() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// define sheeta for Crop Plan and output
var datasheet = "Crop Plan";
var sheet = ss.getSheetByName(datasheet);
//Logger.log("DEBUG: the sheet = "+sheet.getName())
var outputsheet = "Output"
var output = ss.getSheetByName(outputsheet);
// define the data and variables
var headerrow=15; // header row on Crop Plan
var outputarray = []; // array to hold Crop Plan data for update to Output
// find the number of records in the Crop Plan data
// also find the number of beds in the Crop Plan data
var CLR = sheet.getLastRow();
var Crange = sheet.getRange(headerrow+1,3,CLR);
var Cvals = Crange.getValues();
var Clast = Cvals.filter(String).length;
//Logger.log("DEBUG: Number of rows of data = "+Clast);
// get only the actual rows in the Bed Column (Column C) with data
var newCvals = sheet.getRange(headerrow+1,3,Clast).getValues();
//Logger.log("this is newCvals");
//Logger.log(newCvals)
// convert the format of the 2D data to 1D
var Cdata = newCvals.map(function(e){return e[0];});//[[e],[e],[e]]=>[e,e,e]
//Logger.log("DEBUG: this is c data");
//Logger.log(Cdata); // DEBUG;
// get the unique values
Cdata = Array.from(new Set(Cdata));
// Logger.log("DEBUG: this is the unique values in CData");
// Logger.log(Cdata); //DEBUG
// Logger.log("DEBUG: number of unique beds = "+Cdata.length);
for (var cd = 0;cd < Cdata.length;cd++){
// Logger.log("cd="+cd+", cdata = "+Cdata[cd])
}
// get all the CROP data
var plantingrange = sheet.getRange(headerrow+1,3,Clast,8);
// Logger.log("DEBUG: plantingrange = "+plantingrange.getA1Notation());
var plantingdata = plantingrange.getValues();
for (b=0;b<Cdata.length;b++){
// Logger.log("DEBUG: Cdata: Bed:"+Cdata[b])
for (i=0;i<Clast;i++){
var cropline = [];
//Logger.log("DEBUG: Planting data: Bed:"+plantingdata[i][0]+", crop:"+plantingdata[i][1]+", seed date:"+plantingdata[i][3]+", trans data:"+plantingdata[i][5]+", harvest date:"+plantingdata[i][7]);
if (plantingdata[i][0] == Cdata[b]){
cropline.push(plantingdata[i][0]); // bed
cropline.push(plantingdata[i][1]); // crop
cropline.push(plantingdata[i][3]); // seed date
cropline.push(plantingdata[i][5]); // trans date
cropline.push(plantingdata[i][7]); // harvest date
outputarray.push(cropline); // push the whole row onto the outout array
}
}
}
// get the number of rows in outputarray
var outputCount = outputarray.length;
// define the output range
var outputLR = output.getLastRow();
// define range on output
var outputCount = outputarray.length;
output.getRange(outputLR+1,1,outputCount,5).setValues(outputarray)
// Logger.log("DEBUG: Crop Plan copied to Outputsheet")
}
Assuming that the header row is already in place, the screen would look like this:

Helper Columns
The answer uses helper columns on sheet "Output". These describe:
the unique crop beds
the first row on which the crop bed appears.
the last row of data
Cell I2: =unique(INDIRECT("A2:A"&ArrayFormula(max(if(len(A:A),row(A:A),)))))
- a dynamic formula that detects the last row, and lists the crops accordingly.
Cell J2: =MATCH(I2,INDIRECT("$A$2:$A$"&$L$2),0)+2
- returns the first row number in which each crop bed appears.
- copy this formula down as many rows as unique beds.
Cell L1: =ArrayFormula(max(if(len(A:A),row(A:A),)))
- this value is used in formulas to reference the end of a range.
Assuming that the header row is already in place, the helper columns would look like this:

Revised Formula: "Max Harvest date" and "Unplanted Days"
The formula originally described assumed a single crop bed, but this is an unrealistic expectation in the grand scheme. So these formula have to be responsive to the crop bed.
Max Harvest Date
- Cell F2:
=max(INDIRECT("$E$"&vlookup(A2,$I$2:$J$6,2,false)&":E"&row()))
- Copy this formula down to the last row of data
Unplanted days
- Cell G2:
=if(C2<=F1,0,C2-F1)
- Copy this formula down to the last row of data
Conditional formatting
- If desired, you can highlight the unplanted days. Select the data range, and use this custom formula
=and(G2>0,isblank(G2)=FALSE)
Output
The final output screen might look like this:

Addendum#2 (23 Jan 2021)
DATA ANALYSIS BY CROP BED
The results for a given "Crop Bed" can be easily analysed using a FILTER
.
In this example, I have created an additional sheet. The headers have been copied longhand.
Selecting a "Crop Bed"
Refer the attached screen shot.
Crop Bed selector
- Cell B1: Data validation from a range
=Output!$A$2:$A$1000
Filter formula
- Cell A3:
=Filter(Output!A2:G, SEARCH( $B$1, Output!A2:A ) )
Filtered Data

unplanted
that not only takes dates into account but also area under cropping. For example, your sample data has Tomatos planted 21 March and harvested 7 June. But Kale is planted after and harvested before Tomatos - so NE1 can support at least two (or more?) crops at any time. There are 254 days between the earliest planting and last harvest, but total days under crop is 578 days. Do you think that there are any daysunplanted
in your sample data?