I have a spreadsheet with worksheets (originally in Google Sheets, but I can export to .xlsx or .ods) and I would like to programmatically print out the cell values of the first line along with the comments in each cell. E.g. see screenshot below of worksheet (https://docs.google.com/spreadsheets/d/1DGsrEKrxfQm8sRzfLyqu4z6Hx8eDdkVDiYlN3Rwve6A/edit?usp=sharing):
There are 3 cells in row1 each with a comment in them.
I would like to programmatically print out the contents of this worksheet so that they look something like:
Cell:"field1",Comment:"key=foobar"
Cell:"field2",Comment:"key=bar"
Cell:"field3",Comment:"key=foobar"
Any ideas?
google-spreadsheets
function getNotes_(fileId, sheetName, rangeA1)
{
var data = [];
var file = SpreadsheetApp.openById(fileId);
var sheet = file.getSheetByName(sheetName);
var range = sheet.getRange(rangeA1);
var values = range.getValues();
var notes = range.getNotes();
var getResult_ = function(value, i) { data.push( 'Cell:"' + value + '",Comment:"' + rowNotes[i] +'"') };
var rowNotes = [];
for (var i = 0, l = values.length; i < l; i++)
{
rowNotes = notes[i];
values[i].forEach(getResult_);
}
return data;
}
Related
I have a script which records the time stamp on which an entry is made in a specific cell. It uses a onEdit trigger.
PROBLEM STATEMENT:
When I'm dragging/copy-pasting the data over a range of adjacent cells(in the same column), only the first entry is producing a time-stamp output.
CODE:
var s = SpreadsheetApp.getActiveSheet();
var sName = s.getName();
var r = s.getActiveCell();
if( r.getColumn() == 8 && sName == 'Processing') { //which column to watch on which sheet
var row = r.getRow();
var time = new Date();
SpreadsheetApp.getActiveSheet().getRange('CU' + row.toString()).setValue(time); //which column to put timestamp in
};
};
You are using onEdit to insert a timestamp when a field is edited. But when an edit is done by copy/paste or dragging a cell/range, the timestamp is applied only for the first cell in the new target range.
The reason that this is happening is that your script output recognises only the activecell and does not recognise the rest of the activerange
var r = s.getActiveCell();
var row = r.getRow();
There are several solutions to your problem.
ActiveRange:
Enable the script to process the number of rows in the active range.
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var sName = s.getName();
var r = s.getActiveCell();
var row = r.getRow();
var ar = s.getActiveRange();
var arRows = ar.getNumRows()
// Logger.log("DEBUG: the active range = "+ar.getA1Notation()+", the number of rows = "+ar.getNumRows());
var time = new Date();
if( r.getColumn() == 8 && sName == 'Processing') { //which column to watch on which sheet
// loop through the number of rows
for (var i = 0;i<arRows;i++){
var rowstamp = row+i;
SpreadsheetApp.getActiveSheet().getRange('CU' + rowstamp.toString()).setValue(time); //which column to put timestamp in
}
}
}
Event Objects: Enable the script to take advantage of the event Objects generated by OnEdit.
In the following script, the edited range, the column, sheet name, the starting and ending row numbers are all obtained/determined by using Event Objects available to onEdit.
function onEdit(event) {
var s = SpreadsheetApp.getActiveSheet();
// Logger.log(JSON.stringify(event)); //DEBUG
var ecolumnStart = event.range.columnStart;
var erowStart = event.range.rowStart;
var erowEnd = event.range.rowEnd;
var ecolumnEnd = event.range.columnEnd;
// Logger.log("DEBUG: Range details - Column Start:"+ecolumnStart+", Column End:"+ecolumnEnd+", Row start:"+erowStart+", and Row End:"+erowEnd);
// Logger.log("DEBUG: the sheet is "+event.source.getName()+", the range = "+event.range.getA1Notation());
var sName = event.range.getSheet().getName();
// Logger.log("DEBUG: the sheet name is "+sName)
var time = new Date();
var numRows = event.range.rowEnd -event.range.rowStart+1;
if( event.range.columnStart == 8 && sName == 'Processing') { //which column to watch on which sheet
// loop though the number of rows
for (var i = 0;i<numRows;i++){
var row = event.range.rowStart+i;
SpreadsheetApp.getActiveSheet().getRange('B' + row.toString()).setValue(time); //which column to put timestamp in
}
}
}
I have created an API that searches sheet 2 in a spreadsheet for a keyword and returns the number of the row of the cell that the key word was found in. I want to copy and paste all the rows from sheet 2 on to sheet 1. I can't get the script to copy and paste them all.
function executeSearch() {
//establishing search sheet
var SSS = SpreadsheetApp.openById('ID');
var SS = SSS.getSheetByName('Sheet1');
var searchTerm = SS.getRange('B3').getValue();
//establishing the data sheet
var DS = SSS.getSheetByName('Sheet2');
var completeSearch = DS.createTextFinder(searchTerm).findAll();
for (var i = 0; i < completeSearch.length; i++) {
var range = completeSearch[i];
var resultsCells = range.getA1Notation(); //get the cell location of the search data cell
var row = range.getRow(); //get the rows that the search data is in
DS.getRange(row, 1, 1, DS.getMaxColumns()).copyTo(SS.getRange(8, 1, 1, DS.getMaxColumns()));
}
Your code is copying the data to the same row each time:
DS.getRange(row, 1, 1, DS.getMaxColumns()).copyTo(SS.getRange(8, 1, 1, DS.getMaxColumns()));
To get the code to write the data to new rows, you can change it to:
DS.getRange(row, 1, 1, DS.getMaxColumns()).copyTo(SS.getRange(8 + i, 1, 1, DS.getMaxColumns()));
But this isn't efficient when you have a large number of results. You are repeatedly calling the sheet for writing each row.
It would be more efficient to first write all the search results to an array. And then to call the sheet just once to write all the data to the rows in one go.
function executeSearch() {
//establishing search sheet
var SSS = SpreadsheetApp.openById('ID');
var SS = SSS.getSheetByName('Sheet1');
var searchTerm = SS.getRange('B3').getValue();
//establishing the data sheet
var DS = SSS.getSheetByName('Sheet2');
var completeSearch = DS.createTextFinder(searchTerm).findAll();
var searchResults = []; // Create an array to store the values of the search results
for (var i = 0; i < completeSearch.length; i++) {
var range = completeSearch[i];
var row = range.getRow(); //get the rows that the search data is in
var values = DS.getRange(row, 1, 1, DS.getMaxColumns()).getValues();
searchResults.push(values[0]);
}
SS.getRange(8, 1, searchResults.length, searchResults[0].length).setValues(searchResults);
}
The only thing to watch out for in this script is that it will write values to the sheet and not formulas.
I want to copy paste from excel to webpage. This issue is resolved using Copy/Paste from Excel to a web page
However now I want these fields to be editable and submit it in a form. So I changed the code to :
function generateTable() {
var data = $('textarea[name=excel_data]').val();
console.log(data);
var rows = data.split("\n");
var table = $('<table />');
var counterRow = 0;
var counterCol = 0;
for(var y in rows) {
var cells = rows[y].split("\t");
var row = $('<tr />');
for(var x in cells) {
row.append('<td border-collapse:collapse>' + '<textarea style="overflow:auto" name=' + counterRow + counterCol + '>' +cells[x]+'</textarea>'+'</td>');
counterCol++;
}
counterRow++;
table.append(row);
}
// Insert into DOM
$('#excel_table').html(table);
}
The problem is : there is an additional row containing 1 cell displayed towards the end of the table.
___________
|___|___|___|
|___|___|___|
|___|
I had to use this if clause inside the for :
if(rows[y]){
I’m trying to get the value of column Notes in Sheet 2 and put it to column Notes of Sheet 1. To do that, they should have the same column Company value. When I enter a value in Company (Sheet 2), the code will find if it has the same value in Company (Sheet 1). If the code finds the same value of Company, the value in Notes (Sheet 2) that I enter will automatically put in Notes (Sheet 1). I used the if/else statement in my code but it is not running.
Any help would be greatly appreciated.
Ex:
Sheet 1
enter image description here
Sheet 2
enter image description here
Here's my code :)
function onEdit() {
var sheetId = SpreadsheetApp.openById('1fx59GrC_8WEU5DCM5y2N8YR3PK936RLqZVknQ66WWUA'); //replace with source ID
var sourceSheet = sheetId.getSheetByName('Notes'); //replace with source Sheet tab name
var notesActiveCell = sourceSheet.getActiveCell();
var notesRow = notesActiveCell.getRow();
var notesComp = SpreadsheetApp.getActiveSheet().getRange('B' + notesRow.toString());
var destSheet = sheetId.getSheetByName('Companies'); //replace with destination Sheet tab name
var compActiveCell = destSheet.getActiveCell();
var compRow = compActiveCell.getRow();
var companies = SpreadsheetApp.getActiveSheet().getRange('B' + compRow.toString());
if (notesComp.getValues() == companies.getValues()) {
Logger.log(notesComp.getValues());
var sourceRange = SpreadsheetApp.getActiveSheet().getRange('C' + notesRow.toString()); //assign the range you want to copy
var notesData = sourceRange.getValues();
destSheet.getRange('F' + compRow.toString()).setValues(notesData);
}
}
There are a lot of errors in your code. I'm not a very experienced programmer, but form what you have said I think the script below should give you a good starting point.
Don't forget, you also need to add an onEdit trigger to run the script when you enter a value.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getActiveSheet();
var sourceCellRow = sourceSheet.getActiveCell().getRowIndex();
var sourceData = sourceSheet.getRange(sourceCellRow, 1, 1, 2).getValues();
var destSS = SpreadsheetApp.openById('Paste destination Spreadsheet ID here');
var destSheet = destSS.getSheetByName('Companies');
var searchData = destSheet.getRange(1, 1, destSheet.getLastRow()).getValues();
for (var i = 0; i < searchData.length; i ++){
if(searchData[i][0] == sourceData[0][0]){
destSheet.getRange(i + 1, 2).setValue(sourceData[0][1]);
break;
}
}
}
Try using the copyTo(destination)
Copies the data from a range of cells to another range of cells. Both the values and formatting are copied.
// The code below will copy the first 5 columns over to the 6th column.
var sheet = SpreadsheetApp.getActiveSheet();
var rangeToCopy = sheet.getRange(1, 1, sheet.getMaxRows(), 5);
rangeToCopy.copyTo(sheet.getRange(1, 6));
}
I think that will be invaluable inside your onEdit() function.\
You might also want to check this sample from this google forum
function Copy() {
var sss = SpreadsheetApp.openById('spreadsheet_key'); //replace with source ID
var ss = sss.getSheetByName('Source'); //replace with source Sheet tab name
var range = ss.getRange('A2:E6'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('spreadsheet_key'); //replace with destination ID
var ts = tss.getSheetByName('SavedData'); //replace with destination Sheet tab name
ts.getRange(ts.getLastRow()+1, 1,5,5).setValues(data); //you will need to define the size of the copied data see getRange()
}
I have an HTML code that I would like to use to send text data to a specific excel spread sheet starting on the next available line and starting with column B. I have a code that opens a new excel spreadseet every time and sends data like it should. I want to modify the code to go to a specific spread sheet and keep adding additional data to the same sheet.
Here is the code that I have so far:
<script>
function ToExcel(){
if (window.ActiveXObject){
var xlApp = new ActiveXObject("Excel.Application");
var xlBook = xlApp.Workbooks.Add();
var table=document.getElementById('inner_table')
//var tableCells=document.getElementById('inner_table').cells
var tableRows=document.getElementById('inner_table').rows
xlBook.worksheets("Sheet1").activate;
var XlSheet = xlBook.activeSheet;
xlApp.visible = true;
var xlRow = 1;
var xlCol = 1;
var R=0;
while(tableRows[R] != null)
{
var tableCells =tableRows[R].cells
var C = 0;
xlCol=1;
while(tableCells[C] != null)
{
XlSheet.cells(xlRow, xlCol).value = tableCells[C].childNodes[1].value;
xlCol++;
C++;
}
xlRow++;
R++;
}
XlSheet.rows.autofit;
XlSheet.columns.autofit;
}
}
</script>
Thanks for any help
You can get the row number for the first empty row on the sheet (looking from the bottom of the sheet up) using something like:
var xlRow = XlSheet.cells(XlSheet.Rows.Count, 1).End(-4162).Row+1 // -4162==xlUp