let workbook = new Excel.Workbook();
for (let i = 0; i < 3; i++){
workbook.addWorksheet('test', {
properties: {tabColor: {argb: 'FF00FF00'}}, views: [
{ySplit: 5, activeCell: 'A1', showGridLines: false}
]
});
}
First worksheet will have 'test' name, others will have an error title. Do you know how to make it work?
EDIT : If i generate my worksheet in a function, it works.
let workbook = new Excel.Workbook();
function generateWorksheet(data){
workbook.addWorksheet('test', {
properties: {tabColor: {argb: 'FF00FF00'}}, views: [
{ySplit: 5, activeCell: 'A1', showGridLines: false}
]
});
}
for (let i = 0; i < 3; i++){
generateWorksheet(i);
}
I think the issue is that you can't create multiple worksheets with the same name. So append the loop index to each worksheet.
let workbook = new Excel.Workbook();
for (let i = 0; i < 3; i++){
workbook.addWorksheet('test'+i, {
properties: {tabColor: {argb: 'FF00FF00'}}, views: [
{ySplit: 5, activeCell: 'A1', showGridLines: false}
]
});
}
So now the worksheet name would be test plus the loop index.
Related
I am very new to excel but I have been coding for a couple of years. Now I have created a function which returns an array of objects.
function sheetnames() {
var out = new Array()
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i=0 ; i<sheets.length ; i++){
let totalScore = sheets[i].getRange("C2").getValue();
if(i == 0 || i == 1){
continue;
}
console.log(sheets[i].getName(), totalScore);
out.push({name: sheets[i].getName(), score: totalScore});
}
return out.sort((a)=> a.totalScore);
}
I want to call this function and write Name in A1 and score in B1 and then next row Name in A2 and score in B2 and so on and so on.
I'm calling my function in excel using =sheetnames() which i got to work before when I only returned an array with strings.
Thanks!
I solved it by updating the excelsheet straigt from the code instead of calling the function from the acctual excel.
function sheetnames() {
resetStandingsSheet();
var out = new Array()
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i=0 ; i<sheets.length ; i++){
let totalScore = sheets[i].getRange("C2").getValue();
if(i == 0 || i == 1){
continue;
}
console.log(sheets[i].getName(), totalScore);
out.push({name: sheets[i].getName(), score: totalScore});
}
var scoresAndNames = out.sort((a)=> a.totalScore);
var standingSheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
standingSheet.appendRow(["Name", "Score"]);
for(var i = 0; i < scoresAndNames.length; i++){
standingSheet.appendRow([scoresAndNames[i].name, scoresAndNames[i].score + 'p']);
}
}
I can't perform multiple delette from my listbox although I made the listbox mutiselect Why ??
I need your help . You can see the full Script down there.
(function(){
$.win = new Window("palette");
var win = $.win;
win.orientation = "column";
win.alignChildren = ["center", "top"];
win.spacing = 10;
win.margins = 16;
var listbox1 = win.add("listbox", undefined, undefined, { name: "listbox1", multiselect: true, columnTitles: "Max", showHeaders: true });
listbox1.preferredSize.width = 136;
listbox1.preferredSize.height = 208;
var button1 = win.add("button", undefined, undefined, { name: "button1" });
button1.text = "Search";
var button2 = win.add("button", undefined, undefined, { name: "button2" });
button2.text = "Delete";
win.show();
var myNewArray = [];
button1.onClick = function Search() {
var compsArray = new Array();
var myProj = app.project;
myNewArray = [];
listbox1.removeAll();
for (var i = 1; i <= myProj.numItems; i++) {
if (myProj.item(i) instanceof CompItem) {
myNewArray = compsArray[compsArray.length] = myProj.item(i);
listbox1.add("item", myNewArray.name);
}
}
}
button2.onClick = function deletecomps() {
for (var s = 1; s <= app.project.numItems; s ++) {
if ((app.project.item(s) instanceof CompItem) && (app.project.item(s).name.match(listbox1.selection))) {
myComp = app.project.item(s);
break;
}
}
app.project.item(s).remove ();
}
})();
You can see an image to clarify the script in AE
Your problem is that listbox1.selection in line 34
if ((app.project.item(s) instanceof CompItem) && (app.project.item(s).name.match(listbox1.selection))) {
is an array, and you're trying to match it to a string returned by app.project.item(s).name which is never going to match.
Also, what are you trying to achieve with the lines
myComp = app.project.item(s);
break;
Here's the onClick function, but it works. It loops through the selection, and looks for a matching project item, based on the text of the listbox matching the comp's name. This is dangerous, because identical comp names would create false positives. I strongly suggest you don't use this technique in production code, because it will definitely cause problems for your users.
Also I'd turn the part wherre you populate the list into a separate function, and call it after you click delete, so that the list is refreshed, because at the moment the list stays the same, even after the comp is deleted.
button2.onClick = function deletecomps() {
for (var b= 0; b < listbox1.selection.length; b++){
for (var s = 1; s <= app.project.numItems; s ++) {
if ((app.project.item(s) instanceof CompItem) && (app.project.item(s).name.match(listbox1.selection[b].text))) {
app.project.item(s).remove ();
}
}
}
}
Here's how I declare my array of objects:
let arrayOfObjects = [{ _id:0, names:'' }];
And I want to assign the values like below:
for (var i = 0; i < kelasList.length; i++){
for (var j = 0; j < absentees[i].length; j++){
arrayOfObjects[i]._id = absentees[i][j]._id
arrayOfObjects[i].names = absentees[i][j].firstName + " " + absentees[i][j].lastName
}
}
Running the code above will return
UnhandledPromiseRejectionWarning: TypeError: Cannot set property '_id' of undefined at line
which basically points to the line
arrayOfObjects[i]._id
But it will assign the value without any problem, if I write
arrayOfObjects[0]._id
instead of
arrayOfObjects[i]._id
My assumption was let arrayOfObjects = [{ _id:0, names:'' }]; would create an array of objects, so I would be able to access/set its values with
arrayOfObjects[i]._id
but it seems let arrayOfObjects = [{ _id:0, names:'' }]; here will only create a single array of object. So currently for me to pass more values, I will need to declare it something like
let arrayOfObjects = [{ _id:0, names:'' },{ _id:0, names:'' },{ _id:0, names:'' },{ _id:0, names:'' },{ _id:0, names:'' }];
But of course, this isn't feasible because I don't know what should my array size be. So actually how should I declare the array of objects that can contain dynamic size of objects?
You could simply check if the element already exists in the array and if it doesn't, create it.
let arrayOfObjects = [];
for (var i = 0; i < kelasList.length; i++) {
for (var j = 0; j < absentees[i].length; j++) {
if (!arrayOfObjects[i]) {
arrayOfObjects[i] = {
_id: 0,
names: ''
};
}
arrayOfObjects[i]._id = absentees[i][j]._id
arrayOfObjects[i].names = absentees[i][j].firstName + " " + absentees[i][j].lastName
}
}
By setting arrayOfObjects[i]._id, you are setting the attribute _id on an already existing object arrayOfObjects[i]. But for i >= 1, this object doesn't exist.
Instead, you need to set the whole object in the loop:
for (var i = 0; i < kelasList.length; i++){
for (var j = 0; j < absentees[i].length; j++){
arrayOfObjects[i] = {
_id: absentees[i][j]._id,
names: absentees[i][j].firstName + " " + absentees[i][j].lastName}
}
}
This will work just fine, but will replace the whole object at the index i. If instead you want to set the _id and names attribute of an object that could already be existing with different keys (say, address), you would check if the object exists:
for (var i = 0; i < kelasList.length; i++){
for (var j = 0; j < absentees[i].length; j++){
let id = absentees[i][j]._id;
let names = arrayOfObjects[i].names = absentees[i][j].firstName + " " + absentees[i][j].lastName;
if(arrayOfObjets[i]){
arrayOfObjects[i]._id = id;
arrayOfObjects[i].names = names;
}else{
arrayOfObjects[i] = {
_id: absentees[i][j]._id,
names: absentees[i][j].firstName + " " + absentees[i][j].lastName
}
}
}
}
There is one last problem with your code. You are iterating over i, then over j, and are setting arrayOfObjects[i]. This means that your double loop is basically the same thing as:
for (var i = 0; i < kelasList.length; i++){
let lastAbsentee = absentees[i][absentees[i].length-1];
arrayOfObjects[i]._id = lastAbsentee._id
arrayOfObjects[i].names = lastAbsentee.firstName + " " + lastAbsentee.lastName
}
Are you sure that is what you want to do? Somehow I would be doubting it.
Your arrayOfObjects has a size of 1 when you initialize it, but then you look into arrayOfObjects[i] after i === 0 which cause the undefined behavior since there are no items there (yet).
In your for loop, you're also overwriting on arrayOfObjects[i] multiple times (j times to for precision).
Try using this
let arrayOfObjects = [];
for (var i = 0; i < absentees.length; i++) {
for (var j = 0; j < absentees[i].length; j++) {
arrayOfObjects.push({
_id: absentees[i][[j]._id,
names: absentees[i][j].firstName + " " + absentees[i][j].lastName
});
}
}
NOTE: The iteration logic may be subject to change since I didn't really get your intention from your code. The "adding items to the arrray" part is good though.
I have a huge problem with ParamQuery. I'm using the updateRow method for update a row below the documentation:
$( ".selector" ).pqGrid( "updateRow",
{ rowIndx: 2, row: { 'ProductName': 'Cheese', 'UnitPrice': 30 } );
However I need that 'ProductName', 'UnitPrice', etc.. etc... will be programmatically read from an array of values. How can I do it?
For example if my array at position 2 contains ProductName it's not possible to do
$( ".selector" ).pqGrid( "updateRow",
{ rowIndx: 2, row: { **myArray[2]**: 'Cheese', 'UnitPrice': 30 } );
Any ideas?
thanks in advance.
Solution
var obj = {};
for(var i = 0; i < myarray.length; i++) {
var key = myarray[i];
var val = '44';
obj[key] = val;
}
$( ".selector" ).pqGrid( "updateRow",
rowIndx: 2,
row: obj
});
thanks anyway :)
Is it possible to create an Excel format file from a Google sheet using Google script, so that it can be added as an attachment to an email?
I've got a code that takes columns with certain names (e.g. A, C, F) and turns them into a new sheet (on createCustomStatusTable() function).
https://docs.google.com/spreadsheets/d/1fZ0JMYjoIrfPIxFBVgDNU0x5X0ll201ZCU-lcaTwwcI/edit?usp=sharing
var expected = ['A','C','F'];
var newSpreadSheet = SpreadsheetApp.getActiveSheet();
var tableLastRow = newSpreadSheet.getLastRow();
var tablelastColumn = newSpreadSheet.getLastColumn();
var values = newSpreadSheet.getRange(1, 1, tableLastRow, tablelastColumn).getValues();
var rangeToCopy = [];
function in_array(value, array)
{
for(var i = 0; i < array.length; i++)
{
if(array[i] == value) return true;
}
return false;;
};
function columnsCount() {
var count = 1;
for (var i = 0; i < SpreadsheetApp.getActiveSheet().getLastColumn(); i++) {
if (in_array(values[0][i],expected))
count++;
}
return count;
};
function returnRange() {
for (var i = 1; i < SpreadsheetApp.getActiveSheet().getLastColumn()+1; i++) {
if (in_array(values[0][i-1],expected)) {
rangeToCopy.push(newSpreadSheet.getRange(1, i, newSpreadSheet.getMaxRows()));
};
};
return rangeToCopy;
};
function createCustomStatusTable() {
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Target');
for (var i = 1; i < columnsCount(); i++) {
returnRange()[i-1].copyTo(targetSheet.getRange(1,i));
};
};
Thank you in advance for any help
You can create an EXCEL type file with DriveApp:
The problem is, that the content must be a string. And I haven't tested for a way to make that work.
I know this doesn't answer your question. Hopefully someone knows for sure how to create an EXCEL file from a Google Sheet.