问题
I'm fairly new to GDS and I'm loving it so far. What I'm trying to do is have a Google sheet containing requirements and quantity for a specific job, and then use the Data Studio to be able to search by the requirement and have the quantity in the same field.
I've mocked up some examples of what I currently have:
https://datastudio.google.com/open/1z0SIYa0ucpBiJXf_IQBaIsu61INP71Hc
https://docs.google.com/spreadsheets/d/1eUhE3chM77etyTcv4E7jyB_6vCFxSYArMyF2ptxK180/edit?usp=sharing
If I combine the quantity with the materials, I lose the ability to search by that material in the data studio. I'd like to be able to have just two columns and someone types in Mat X and all the jobs with that come up with the quantities in the same column.
I know I could accomplish something similar by having N amount of columns for each material and have that contain the quantity but is not practical for my application.
Thanks for you time.
回答1:
Data Studio can't filter on Material because it can't identify the unique components.
I suggest that you create a second table in the spreadsheet that is created by a script/macro, and which lists the materials and quantities by job. This sheet is the source for Data Studio, and so it will enable filtering by Job or Material. The table can be updated at any time by running the macro.
The table might look like this:
The output in data Studio would look like this:
Here's a sample of Data Studio.
Were this Excel, the VBA would be easy to write, but Google Scripts uses Javascript so it will certainly take me a bit longer (though others would be far more adept) to provide a sample of code to achieve the new spreadsheet.
The Google Scripts logic is:
For each job
- count the number of commas in the requirements. Number of requirements = CommaCount plus one.
- Parse requirements to get qty and material details
- Copy first qty/materials into columns C & D for this job.
- For each additional requirements, duplicate the Job row, and copy the additional qty/materials into respective Columns C & D.
In Data Studio
- Insert Table; Dimension:Job, Requirement; Sort: Job Ascending.
- Insert Filter; Dimension: Job; Sort: Job Ascending.
- Insert Filter; Dimension: Material; Sort: Material Ascending.
UPDATE This code fulfils the objective outlined above - to have a second sheet that services the GDS. It takes the raw job information and builds a sheet of data, identifying each combination of material and quantity for each job. The code is probably not as efficient as it might be but the more important thing at this stage is - it works.
Three assumptions: 1) always more than one material per job; 2) material-code contains no spaces; 3) quantity is always an integer.
Quick Summary
There is one "master" function that can be assigned to a button on the GDS_data sheet. This makes rebuilding the GDS data extremely easy.
The Functions are:
- BuildGDSData - the main function
- CountJobs - counts, well...., the number of jobs
- CountMaterials - counts the number of requirements for each job
- CreateJobRows - inserts new rows so that there is one row per job per requirement
- BuildMaterials - parses the job requirements, and populates the "Material" and "Qty" columns for each row of the job.
The new Data Studio Page
// Convert Job info for GDS
function BuildGDSData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getSheetByName('jobinfo');// assumes basic job info is on sheet called "jobinfo"
var target = ss.getSheetByName('gds_data');// assumes that the GDS data is build on a sheet called "gds_data"
// Start gds_data from scratch. Delete everything
target.clearContents();
target.clearFormats();
// Get the data range from sheet = jobinfo
var rangeToCopy = source.getRange(1, 1, source.getMaxRows(),source.getMaxColumns());
// Paste the data to the cheet=gds_data
rangeToCopy.copyTo(target.getRange(1, 1));
// Add headings on sheet=gds_data for Material and Qty
target.getRange('C1').setValue('Material');
target.getRange('D1').setValue('Qty');
// Move the cursor to cell B2 on sheet = gds_data- this is the start of the job information
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getRange('B2:B2');
sheet.setActiveRange(range);
// Call function CountJobs; assign number to jobs to variable "job_count"
var job_count = CountJobs();
// execute loop for the number of jobs
for (var i = 0; i < job_count; i++) {
// Call function CountMaterials; assign the number of materials for the job to variable MatCount
var MatCount = CountMaterials();
// Copy and insert new rows for the job so that there is one row per requirement. Copy the job details onto each new row
// Number of rows to create = for this job, the number of materials minus one. The "one" is row of job information that already exists.
CreateJobRows ((MatCount-1));
// Parse the requirements and copy the results to the Materials and Qty columns
BuildMaterials();
}
}
// Count and return the number of Jobs = number of rows of data minus one. the "one" is the header row,
function CountJobs() {
var numRows = SpreadsheetApp.getActiveSpreadsheet().getLastRow();
var numCols = SpreadsheetApp.getActiveSpreadsheet().getLastColumn();
return (numRows-1);
}
// Count and return the number of Materials for the current job; Quantity = number of commas plus 1
function CountMaterials(){
var activeSheet = SpreadsheetApp.getActiveSheet();
var selection = activeSheet.getSelection();
// get the requirments value for this job
var text = selection.getCurrentCell().getValue();
// use the split command to explode the requirments. Split by comma.
var textArray = text.split(",");
// Couht the number of components created by the split
var Num_Materials = textArray.length;
// Return the number of Components
return Num_Materials;
}
// Create new rows to cater for each requirment on the job. The count variable identifies the number of rows to create
function CreateJobRows(count) {
var sheet = SpreadsheetApp.getActiveSheet();
for (var i = 0; i < count; i++) {
// get the current row number
row = sheet.getActiveCell().getRow();
// insert a new row after the current row
sheet.insertRowAfter(row);
//copy the contents from cells A and B of the current row to the new row
var rangeToCopy = sheet.getRange(row, 1, 1, 2);
rangeToCopy.copyTo(sheet.getRange(row+1, 1));
}
}
// Parse the requirements and copy the results to the Materials and Qty columns
function BuildMaterials(){
var activeSheet = SpreadsheetApp.getActiveSheet();
var selection = activeSheet.getSelection();
// Before you start, get the current row and current column and assign the valuares to variables.
job_row = activeSheet.getActiveCell().getRow();
job_col = activeSheet.getActiveCell().getColumn();
// Get the requirements for this job
var text = selection.getCurrentCell().getValue();
// Split by comma and put the requirments into an array
var textArray = text.split(",");
// Count the number of components in the array
var NumRequirements = textArray.length;
for (var i = 0; i < NumRequirements; i++) {
// establish some variables and ensure that values from a previous loop don't carry over
var req_string = "";
var req_array = [];
var req_data = [];
var qty="";
var material = "";
// get the component; trim just in case
req_string = textArray[i].trim();
// put the component into its own array (req_array)
var req_array = req_string.split(" ");
// get values for quanity and material
qty = req_array[0];
material= req_array[1];
// assign values for quanty and material type to new array. Order of Qty and Material is different.
req_data[0] = material;
req_data[1] = qty;
// create array in format that Google Sheets requires.
var req_results = [req_data];
// define range to copy the results
ResultsRange = activeSheet.getRange((job_row+i), (job_col+1), 1, 2);; // getRange(row, column, numRows, numColumns)
// insert values for Materials and Qty into the respective columns on the relevant row.
ResultsRange.setValues(req_results);
} // repeat for next requirement
// Finished requirements for this job.
// Move the cursor down to the next job (rows=Number of Requirements)
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getRange((job_row+NumRequirements), 2, 1, 1); // getRange(row, column, numRows, numColumns)
sheet.setActiveRange(range);
}
来源:https://stackoverflow.com/questions/52376162/combining-column-data-in-google-data-studio