call function which writes array to range - arrays

I am trying to change my scripts to use the new google analytics API within Google Docs.
I am perfectly able to retrieve my data as an array from the api which might look like:
[["01", "5", "5"], ["02", "0", "0"], ["03", "2", "2"], ["04", "2", "6"], ["05", "46", "73"], ["06", "15", "18"], ["07", "7", "7"]]
Where I am looking for some help is on how to write this to a cell. I used to do so with the v2 API, but am struggling here. (just do not understand why my old method is not working).
What I would like to do:
Call a the function from a cell (randomly chosen)
drop the results from the array to a range in my sheet. The cell where I call the function should be the first cell to write the data.
The beginning of the function would be:
function testAnalytics() {
var id = "ga:XXXXXXXX";
var startdate = "2012-01-01";
var enddate = "2012-07-31";
var metrics = "ga:visits, ga:pageviews";
var optArgs = {dimensions: "ga:month"};
var grabData = Analytics.Data.Ga.get(id,startdate, enddate,metrics,optArgs);
// Browser.msgBox(grabData.getRows()); // test to see if data is correctly received
var returnVal = grabData.getRows();
return returnVal;
/* write returnVal to active cell on active spreadsheet */
}

Try
var sheet = SpreadsheetApp.getActiveSheet();
var thisCell = SpreadsheetApp.getActiveRange();
var row = thisCell.getRow();
var col = thisCell.getColumn();
//Assuming every row in the 2D array has the same number of elements.
sheet.getRange(row, col, returnVal.length , returnVal[0].length).setValues(returnVal);
If you want it to write to any other cell, change thisCell appropriately.
Note I haven't tested this myself so if there are syntax errors, please feel free to correct them :)

Related

Join String and Number to form an array name

Here's what I would like to do.
number = [ 0, 1, 2]
array0 = [ "AA", "BB"]
array1 = [ "CC", "DD"]
array2 = [ "EE", "FF"]
I want to be able to be able to reference the name of the array by doing something like this.
selectedArray = "array" + String(number[2])
then with this, I would like to be able to reference the values inside such as
print("array2:\(selectedArray[1]))
/// The answer would be --> array2:FF
Right now, I've not been able to achieve this, and I tried this but it doesn't work.
selectedArray = Array("array" + String(number[2]))
I tried googling but not knowing how to describe this, I didn't fare well in the results.
Note : The array is a list of GPS Dist / Lat / Lon (very long) and rather than have 1 very huge array, I'm thinking of splitting them out into eg: 10 diff arrays
Not sure I understand correctly what you are trying to achieve and the logic but you can create an array of arrays (lat and long). Something like this:
let number = [0,1,2] // not sure why you need this array
let array = [[ "AA", "BB"],
[ "CC", "DD"],
[ "EE", "FF"]]
let selectedNumber = number[2]
print("array\(selectedNumber):\(array[selectedNumber][1])")
However, I would advice to use this approach:
create a Model for you Coordinates
struct Coordinates {
var lat:String //this should be a Double but
//for the sake of the example I use String
var long:String //Same here
}
then in the controller add data to an array of Coordinates
let coordinate1 = Coordinates(lat: "AA", long: "BB")
let coordinate2 = Coordinates(lat: "CC", long: "DD")
let coordinate3 = Coordinates(lat: "EE", long: "FF")
let array2:[Coordinates] = [coordinate1,coordinate2,coordinate3]
let selectedNumber = number[2]
print("array\(selectedNumber):\(array2[selectedNumber].long)")
which still prints
array2:FF

Google Apps Script: how to create an array of values for a given value by reading from a two column list?

I have a set of data in a Google spreadsheet in two columns. One column is a list of article titles and the other is the ID of a hotel that is in that article. Call it list1.
Example data
I would like returned a new list with article titles in one column, and an array of the hotel IDs in that article in the other column. Call it list2.
Example data
There are thousands of lines that this needs to be done for, and so my hope was to use Google Apps Script to help perform this task. My original thinking was to
Create column 1 of list2 which has the unique article titles (no script here, just the G-sheets =unique() formula.
Iterate through the titles in list2, looking for a match in first column of the list1
If there is a match:
retrieve its corresponding value in column 2
push it to an empty array in column two of list2
move onto next row in list1
if no longer a match, loop back to step 2.
I've written the following code. I am currently getting a type error (TypeError: Cannot read property '0' of undefined (line 13, file "Code")), however, I wanted to ask whether this is even a valid approach to the problem?
function getHotelIds() {
var outputSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list2');
var lastRow = outputSheet.getLastRow();
var data = outputSheet.getRange(2,1,lastRow,2).getValues();
var workingSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list1');
var lastActiveRow = workingSheet.getLastRow();
var itemIDS = [];
for (var i=1; i<=data.length; i++) {
var currentArticle = data[i][0];
var lookupArticle = workingSheet[i][0];
if (currentArticle === lookupArticle) {
var tempValue = [workingSheet[i][1]];
itemIDS.push(tempValue);
}
}
}
Use a simple google sheets formula:
You can use a very simple formula to achieve your goal instead of using long and complicated scripts.
Use =unique(list1!A2:A) in cell A2 of list2 sheet to get the unique hotels.
and then use this formula to all the unique hotels by dragging it down in column B.
=JOIN(",",filter(list1!B:B,list1!A:A=A2))
You got the idea right, but the logic needed some tweaking. The "undefined" error is caused by the workingSheet[i][0]. WorkingSheet is a Sheet object, not an array of data. Also, is not necessary to get the data from list2 (output), it is rather the opposite. You have to get the data from the list1 (source) sheet instead, and iterate over it.
I added a new variable, oldHotel, which will be used to compare each line with the current hotel. If it's different, it means we have reached a different Hotel and the data should be written in list2.
function getHotelIds() {
var outputSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list2');
var outLastRow = outputSheet.getLastRow();
var workingSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list1');
var lastActiveRow = workingSheet.getLastRow();
var sourceValues = workingSheet.getRange("A2:B" + lastActiveRow).getValues();
var itemIDS = [];
var oldHotel = sourceValues[0][0]; //first hotel of the list
for (var i = 0; i < sourceValues.length; i++) {
if (sourceValues[i][0] == oldHotel) {
itemIDS.push(sourceValues[i][1]);
/*When we reach the end of the list, the oldHotel variable will never be different. So the next if condition is needed. Otherwise it wouldn't write down the last Hotel.
*/
if (i == sourceValues.length - 1) {
outputSheet.getRange(outLastRow + 1, 1, 1, 2).setValues([
[sourceValues[i][0], itemIDS.toString()]
]);
}
} else {
outputSheet.getRange(outLastRow + 1, 1, 1, 2).setValues([
[sourceValues[i - 1][0], itemIDS.toString()]
]);
oldHotel = sourceValues[i][0]; //new Hotel will be compared
outLastRow = outputSheet.getLastRow(); //lastrow has updated
itemIDS = []; //clears the array to include the next codes
}
}
}
I also converted the itemIDS array to a String each time, so it's written down in a single cell without issues.
Make sure each column of the Sheet is set to "Plain text" from Format > Number > Plain Text
References
getRange
setValues
toString()

setFormulas and rangeList

I'm trying to setFormulas over a range of non-contiguous cells. I need a formula (they're all different) set every 30 cells in a single column (c).
It works to setFormula for each cell, but creating 56 variables seems unnecessary. I can get the formulas but not set them as intended. I also tried using getRangeList but I'm not sure that does what I think it does. Any advice?
function test() {
var spreadsheetU09U10 = SpreadsheetApp.openById('some url');
var sheetU09 = spreadsheetU09U10.getSheetByName('TEST');
var sheetU10 = spreadsheetU09U10.getSheetByName('U10');
var sheetDATA = spreadsheetU09U10.getSheetByName('Sheet4');
//U09 SHEET
//var rangeListU09 = sheetU09.getRangeList(['C4','C34','C64','C94','C124','C154','C184','C204','C234','C264','C294','C324','C354','C384','C404','C434','C464','C494',
//'C524','C554','C584','C604','C634','C664','C694','C724','C754','C784']);
//Logger.log(rangeListU09);
var startRow = 4;
var startColumn = 3;
var numRows = sheetU09.getLastRow();
var numColumns = 1;
var range = sheetU09.getRange(startRow, startColumn, numRows, numColumns);
var getFormulasU09 = sheetDATA.getRange('C30:C57').getFormulas();
//Logger.log(getFormulasU09);
Logger.log(getFormulasU09.length);
for (var i = 0; i < getFormulasU09.length; i++) {
var setFormulasU09 = range.setFormulas(getFormulasU09);
Logger.log(setFormulasU09);
startRow = startRow + 29;
}
It isn't clear exactly where the formulas you are using are originating from, but the RangeList class can help reduce the read time, even if you use it just to call getRanges. If the formula is the same in R1C1 format, then you can very effectively use RangeList#setFormulaR1C1.
Assuming you have formulas in one region that must be written verbatim in a disjoint set of cells:
const wb = SpreadsheetApp.getActive();
// Assuming only text formulas, not actual "entered" formulas
const formulas = wb.getSheetByName("formulas").getDataRange()
.getValues()
.map(function (row) { return row[0]; });
const sheet = wb.getSheetByName("some name");
const destinations = [
// Depending on the relationship between destinations, one could programmatically generate these
];
// Efficiently acquire references to multiple disjoint Ranges
const rl = sheet.getRangeList(destinations);
// Assume the i-th formula goes in the i-th range
rl.getRanges().forEach(function (rg, i) {
rg.setFormula(formulas[i]);
});
// The RangeList makes uniformly formatting these disjoint ranges extremely simple
rl.setFontWeight('bold');
...
Reference
- RangeList
You want to put formulas to the individual cells.
You want to put 28 formulas to cells of ['C4','C34','C64','C94','C124','C154','C184','C204','C234','C264','C294','C324','C354','C384','C404','C434','C464','C494', 'C524','C554','C584','C604','C634','C664','C694','C724','C754','C784'] in the sheet of TEST.
If my understanding is correct, how about using values.batchUpdate of Sheets API? The flow of this script is as follows.
Set range list as 1 dimensional array.
Retrieve formulas.
Create request body for sheets.spreadsheets.values.batchUpdate.
In order to use this script, please enable Sheets API at Advanced Google Services and API console. You can see about how to enable Sheets API at here.
Sample script:
function test() {
var spreadsheetId = "### spreadsheetId ###"; // Please set this.
var sheetName = "TEST";
var spreadsheetU09U10 = SpreadsheetApp.openById(spreadsheetId);
var sheetU09 = spreadsheetU09U10.getSheetByName(sheetName);
// var sheetU10 = spreadsheetU09U10.getSheetByName('U10'); // This is not used in this script.
var sheetDATA = spreadsheetU09U10.getSheetByName('Sheet4');
var rangeListU09 = ['C4','C34','C64','C94','C124','C154','C184','C204','C234','C264','C294','C324','C354','C384','C404','C434','C464','C494', 'C524','C554','C584','C604','C634','C664','C694','C724','C754','C784'];
var getFormulasU09 = sheetDATA.getRange('C30:C57').getFormulas();
rangeListU09 = rangeListU09.map(function(e) {return sheetName + "!" + e});
var resource = {
data: rangeListU09.map(function(e, i) {return {range: e, values: [[getFormulasU09[i][0]]]}}),
valueInputOption: "USER_ENTERED",
};
Sheets.Spreadsheets.Values.batchUpdate(resource, spreadsheetId);
}
Note:
From your question, I'm not sure about the detail formulas. If the a1Notation of each formulas is required to be modified, can you provide a sample spreadsheet including the formulas?
Reference:
sheets.spreadsheets.values.batchUpdate
If I misunderstand your question, please tell me. I would like to modify it.
I'm assuming that you want to copy the whole column starting from the cell locations in the array. That wasn't really clear to me.
function test109() {
var ss=SpreadsheetApp.getActive();
var shU09=ss.getSheetByName('35');//formulas get copied into here starting at row 4
var shDATA=ss.getSheetByName('36');//formulas stored in here C30:C57
var fA=shDATA.getRange('C30:C57').getFormulas();
var dA=['C4','C34','C64','C94','C124','C154','C184','C204','C234','C264','C294','C324','C354','C384','C404','C434','C464','C494','C524','C554','C584','C604','C634','C664','C694','C724','C754','C784'];
for(var i=0;i<dA.length;i++){
var rgs=Utilities.formatString('%s:%s',dA[i],shU09.getRange(dA[i]).offset(fA.length-1,0).getA1Notation());//this uses range.offset to calculate the correct range in A1Notation.
shU09.getRange(rgs).setFormulas(fA);
}
}
As it turns out I just noticed that there are 28 locations and 28 formulas. Perhaps that was intentional and you want to copy a different formula in each location then this version would do that.
function test109() {
var ss=SpreadsheetApp.getActive();
var shU09=ss.getSheetByName('35');//formulas get copied into here starting at row 4
var shDATA=ss.getSheetByName('36');//formulas stored in here C30:C57
var fA=shDATA.getRange('C30:C57').getFormulas();
var dA=['C4','C34','C64','C94','C124','C154','C184','C204','C234','C264','C294','C324','C354','C384','C404','C434','C464','C494','C524','C554','C584','C604','C634','C664','C694','C724','C754','C784'];
for(var i=0;i<dA.length;i++){
shU09.getRange(dA[i]).setFormula(fA[i][0]);
}
}
Range Offset

How to compare array of dates (Strings) with single date in swift 3

I have array of dates (strings) which are coming from local data base like following.
datesFromDBArray:["04/12/2017 07:10:41", "04/12/2017 07:12:17", "04/12/2017 07:13:54", "04/12/2017 07:17:45", "04/12/2017 07:18:56", "05/12/2017"]
Here, same date can have multiple times.
Also from same data base, I am getting some other data called actions.
ActionsDBArray:["1", "6", "1", "1", "1", "2", "2", "2", "4", "1", "5", "2", "3"]
these above two data getting from local database. And both arrays number of count is equal.
Now, I am getting number of dates from server response. That is like
TotalDaysServerArray:["22/11/2017 11:59:59", "23/11/2017 11:59:58", "24/11/2017 11:59:57"]
Here, I am showing TotalDaysServerArray data in table view.
So, here, If user pressed on first cell like 22/11/2017 11:59:59, I need to check this date (not time, only same date) is existed in datesFromDBArray, if existed, then need to check how many indexes its existed, and need to fetch ActionsDBArray same indexes data.
So, I need to get the list of ActionsDBArray indexes and need to show the list of that in some other place.
I have tried some logic which was not worked, so, I am posting query here.
Can anyone suggest me, how to achieve this?
let clickedStr = TotalDaysServerArray[indexPath.row]
let str = clickedStr.components(separatedBy: " ").first
for(index , value) in datesFromDBArray.enumerated() {
if str == value.components(separatedBy: " ").first! {
print(ActionsDBArray[index])
}
}
It's child's play , Don't know where you stuck in logic
Note: I have added First object manually in 04/12/2017 07:10:41 to test the logic
var datesFromDBArray = ["04/12/2017 07:10:41", "04/12/2017 07:12:17", "04/12/2017 07:13:54", "04/12/2017 07:17:45", "04/12/2017 07:18:56", "05/12/2017"]
var ActionsDBArray = ["1", "6", "1", "1", "1", "2", "2", "2", "4", "1", "5", "2", "3"]
var TotalDaysServerArray = ["04/12/2017 11:59:59","22/11/2017 11:59:59", "23/11/2017 11:59:58", "24/11/2017 11:59:57"]
let findingValue = TotalDaysServerArray.first!
print(findingValue)
let index = datesFromDBArray.index { (string) -> Bool in
string.components(separatedBy: " ").first == findingValue.components(separatedBy: " ").first
}
print(index)
if let i = index {
print("Your Object in ActionsDBArray \(ActionsDBArray[i])")
}
Output :
04/12/2017 11:59:59
Optional(0)
Your Object in ActionsDBArray 1
Hope it is helpful to you

Retrieving Array from Parse

I created an array that contains different numbers and each time the button is clicked the array advances to the next index number.
var currentNumber = 0
var random = ["1", "2", "3", "4", "5", "6"]
#IBAction func numberUp(sender: UIButton)
numberLabel.text = random[currentNumber]
++currentNumber
I tried to get similar results in with Parse but i couldn't. I created a class with a array in it
var numbers = PFObject(className:"Numbers")
numbers["number"] = ["1","2","3","4","5","6"]
numbers.save()
How would i go about doing the same thing but with the array i created on Parse. Or how could i retrieve the array from Parse and assign it to a local array ?
First you have to create a PFQuery like
let query = PFQuery(className: "Numbers")
Create a query to download the data in the table:
let result = query.find()
Then assume you have only one row in the table:
let arrayOfNumbers = result.first
Then you can iterate on arrayOfNumbers

Resources