The table (master) has links that point to cells within the table.
When creating a copy of this table (master copy), these links lead to the original table (master).
How can I automatically change the links so that they in the copy (master copy) refer to cells inside the copy (master copy)?
I'll link the script to the "fix links" button.
Link to table - https://docs.google.com/spreadsheets/d/1Jrpjm7Yjwp-3WTFKyBz87laPeq6ksjwPaaiWWNcIoow/edit?usp=sharing
I think it can be done by replacing #gid (sheetID) in the links. I found information how to get #gid (sheetID) - Google Apps Script, Google Sheets - Getting Spreadsheet ID and Sheet ID programmatically
But I don't know how to automatically find and replace all #gid (sheetID) in the current table in the links.
You can do it manually using Find and Replace. But it needs to be automated.
I believe your goal is as follows.
From your provided sample Spreadsheet, you want to change the hyperlinks in the range of "I6:I10" with the active sheet instead of the original sheet.
In this case, how about the following sample script?
Sample script 1:
Please copy and paste the following script to the script editor of Spreadsheet and save the script. And, as a test, please copy master, and please open the copied sheet. And then, please run this script. By this, the hyperlinks in the range of "I6:I10" are changed from the original sheet to the currently active sheet.
function myFunction() {
const checkRange = "I6:I10"; // This is from yoru sample Spreadsheet.
const sheet = SpreadsheetApp.getActiveSheet();
const sheetId = sheet.getSheetId();
const range = sheet.getRange(checkRange);
const richTextValues = range.getRichTextValues().map(r => r.map(c => {
const link = c.getLinkUrl();
return link ? c.copy().setLinkUrl(link.replace(/#gid\=.*&/, `#gid=${sheetId}`)).build() : c;
}));
range.setRichTextValues(richTextValues);
}
Sample script 2:
In this sample script, "master" sheet is copied to the same Spreadsheet with the specific sheet name, and the hyperlinks in the range of "I6:I10" are changed from the original sheet to the currently active sheet.
function myFunction2() {
const newSheetName = "sample"; // Please set the new sheet name by copying "master" sheet.
const checkRange = "I6:I10"; // This is from yoru sample Spreadsheet.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sourceSheet = ss.getSheetByName("master");
const newSheet = sourceSheet.copyTo(ss).setName(newSheetName);
const sheetId = newSheet.getSheetId();
const range = newSheet.getRange(checkRange);
const richTextValues = range.getRichTextValues().map(r => r.map(c => {
const link = c.getLinkUrl();
return link ? c.copy().setLinkUrl(link.replace(/#gid\=.*&/, `#gid=${sheetId}`)).build() : c;
}));
range.setRichTextValues(richTextValues);
}
References:
getRichTextValues()
setRichTextValues(values)
Related
I am in need of assistance with google sheet app script in accomplishing the task of highlighting & copying cells A2:K12 with its current cell formats from Sheet A to another sheet's (Sheet B) last available row. Can someone help me in getting this task complete in a function? I have googled some scripts, but they are not what I am looking for, the ones that I have found are only copying values and I would like to copy with the cell formats as it has color highlights and all in my sheet.
Copy from Sheet to Sheet in same Spreadsheet
function myfunk() {
const ss = SpreadsheetApp.getActive();
const sha = ss.getSheetByName("SheetA");
const shb = ss.getSheetByName("SheetB");
sha.getRange("A2:K12").copyTo(shb.getRange(shb.getLastRow() + 1, 1))
}
copyTo
If you simply use copyTo method on a range you would like to copy, it will copy everything including the formatting. You would need to be specific if you like to copy just values. It is similar to just copy/pasting without the script.
Here is a sample code I wrote to copy data with colored backgrounds in B2:B5 in sheet 1 and copies it to sheet 2 as is.
function myFunction() {
const ss = SpreadsheetApp.getActive();
const sheet1 = ss.getSheetByName('Sheet1');
const sheet2 = ss.getSheetByName('Sheet2');
const copyFromRange = sheet1.getRange("B2:B5");
const copyToRange = sheet2.getRange("B2:B5");
copyFromRange.copyTo(copyToRange)
}
You should look in copyTo explaination which has other attributes that you can specify under copypastetype.
I have 25 tabs in a Google Spreadsheet, but this number slowly grows as more data is added. The importrange function that we are provided by default requires the specification of which sheets to import data from using something like what was outlined here: Combining multiple spreadsheets in one using IMPORTRANGE. However, is there a way (using a default function or the Apps Script) to do this for all tabs in the Google Spreadsheet, without specifying each one individually?
I believe your goal is as follows.
You want to retrieve the values from all sheets in a Google Spreadsheet and want to put the values to a sheet of the destination Spreadsheet. In this case, you want to set a range you want to retrieve.
You want to achieve this using Google Apps Script.
Sample script:
Please copy and paste the following script to the script editor of Google Apps Script, and set the variables. And, run the function.
function myFunction() {
const range = "A1:E3"; // Please set the range you want to retrieve.
const srcSpreadsheetId = "###"; // Please set source Spreadsheet ID.
const dstSpreadsheetId = "###"; // Please set destination Spreadsheet ID.
const dstSheetName = "Sheet1"; // Please set destination sheet name.
const values = SpreadsheetApp.openById(srcSpreadsheetId).getSheets().flatMap(s => s.getRange(range).getValues());
const dstSheet = SpreadsheetApp.openById(dstSpreadsheetId).getSheetByName(dstSheetName);
dstSheet.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
}
When this script is run, the values are retrieved from the specific range of all sheets from the source Spreadsheet, and the values are put to the destination sheet.
In the above script, the retrieved values to "A1" of the destination sheet. If you want to append the values, please modify as follows.
From
dstSheet.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
To
dstSheet.getRange(dstSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
Unfortunately, I'm not sure whether I could correctly understand your question. So, for example, if you want to retrieve the values from all sheets except for multiple sheets, and you want to put the retrieved values to the specification sheet in the same Spreadsheet, how about the following sample script? In this case, you can use this script as a custom function. So, when you use this script, please put a custom function of =SAMPLE("A1:E3", "Sheet2,Sheet3") to a cell. In this sample arguments, the values are retrieved from the range of "A1:E3" of all sheets except for "Sheet2" and "Sheet3".
function SAMPLE(range, exclude) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const excludeSheets = [ss.getActiveSheet().getSheetName(), ...exclude.split(",").map(e => e.trim())];
return ss.getSheets().flatMap(s => {
if (!excludeSheets.includes(s.getSheetName())) {
return s.getRange(range).getValues();
}
return [];
});
}
As another pattern, if you want to retrieve the values from all sheets in a source Spreadsheet to a sheet of destination Spreadsheet, how about the following sample script? In this sample, please copy and paste the following script to the script editor of the destination Spreadsheet. And, please set the variables of source Spreadsheet ID and range you want. When this script is run, a formula is put to the cell "A1" of the destination sheet. The formula is from this thread. By this, you can see the values from all sheets in the source Spreadsheet at the destination sheet.
function myFunction2() {
const range = "A1:E3"; // Please set the range you want to retrieve.
const srcSpreadsheetId = "###"; // Please set source Spreadsheet ID.
const srcSs = SpreadsheetApp.openById(srcSpreadsheetId);
const url = srcSs.getUrl();
const values = srcSs.getSheets().map(s => `IMPORTRANGE("${url}","'${s.getSheetName()}'!${range}")`);
const formula = `={${values.join(";")}}`;
const dstSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); // Please set the destination sheet name.
dstSheet.clearContents().getRange(1, 1).setFormula(formula);
}
References:
getSheets()
getValues()
setValues(values)
Added:
About your following reply,
I'm using the first block of code that you sent, and it works. However, I want to copy the entire cell so that it also transfers the cell color, in addition to the text content of the cell. How would I modify the first block of code you sent to do that?
Unfortunately, from your question, I couldn't notice that you wanted to copy both the values and the background color of the cells. To achieve this request, the modified script of my 1st script is as follows.
Sample script:
function myFunction() {
const range = "A1:E3"; // Please set the range you want to retrieve.
const srcSpreadsheetId = "###"; // Please set source Spreadsheet ID.
const dstSpreadsheetId = "###"; // Please set destination Spreadsheet ID.
const dstSheetName = "Sheet1"; // Please set destination sheet name.
const { values, backgroundColors } = SpreadsheetApp.openById(srcSpreadsheetId).getSheets().reduce((o, s) => {
const r = s.getRange(range);
o.values = [...o.values, ...r.getValues()];
o.backgroundColors = [...o.backgroundColors, ...r.getBackgrounds()];
return o;
}, { values: [], backgroundColors: [] });
const dstSheet = SpreadsheetApp.openById(dstSpreadsheetId).getSheetByName(dstSheetName);
dstSheet.clearContents().clearFormats().getRange(1, 1, values.length, values[0].length).setValues(values).setBackgrounds(backgroundColors);
}
I have a sheet where one column contains an ID to a Jira ticket.
I would like to automatically convert this to a link to the ticket, based on the value I enter.
E.g. I'll enter SD-1234 into the column, and I would like it to then make it into a clickable link to https://demo.atlassian.net/browse/SD-1234/, but not show the URL int he cell, but the original value I entered (SD-1234).
The column is always E if that helps. Can someone give me a head start with how to script this in Script Editor?
For example, when the cell "E1" has SD-1234, =HYPERLINK("https://demo.atlassian.net/browse/"&E1, E1) is used, the value is SD-1234 with the hyperlink of https://demo.atlassian.net/browse/SD-1234. But in this case, the result cannot be directly shown in the cell "E1". When you want to directly convert SD-1234 in the cell "E1" to SD-1234 with the hyperlink of https://demo.atlassian.net/browse/SD-1234, how about the following sample script?
Sample script:
Please copy and paste the following script and run the function at the script editor. Before you use this, please set the sheet name.
This sample script converts from SD-1234 in the column "E" to =HYPERLINK("https://demo.atlassian.net/browse/SD-1234", "SD-1234").
function sample1() {
const sheetName = "Sheet1"; // Please set the sheet name.
const baseUrl = "https://demo.atlassian.net/browse/";
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
const range = sheet.getRange("E1:E" + sheet.getLastRow());
const values = range.getValues().map(([e]) => [`=HYPERLINK("${baseUrl}${e}", "${e}")`]);
range.setFormulas(values);
}
This sample script converts from SD-1234 in the column "E" to SD-1234 with the hyperlink of https://demo.atlassian.net/browse/SD-1234. In this case, the formula is not used.
function sample2() {
const sheetName = "Sheet1"; // Please set the sheet name.
const baseUrl = "https://demo.atlassian.net/browse/";
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
const range = sheet.getRange("E1:E" + sheet.getLastRow());
const values = range.getValues().map(([e]) => [SpreadsheetApp.newRichTextValue().setText(e).setLinkUrl(baseUrl + e).build()]);
range.setRichTextValues(values);
}
Note:
If your spreadsheet has the 1st header row, please modify "E1:E" + sheet.getLastRow() to "E2:E" + sheet.getLastRow().
References:
map()
Class RichTextValueBuilder
setRichTextValues(values)
Added 1:
From your following comments,
Do I have to set the sheet name? I have several sheets that I always want this function to be applied to (I have currently over 20 sheets in the file).
Also, I've entered this into Script Editor to test, and what do I do from here? There's no save that I can see... and it's not running on my sheet. How can I apply this to my sheet to automatically run whenever a value is entered in the cell?
When the above situations are reflected in the script, it becomes as follows.
Sample script:
Please copy and paste the following script to the script editor and save it. And please edit the column "E" of the sheet. By this, the cell has the hyperlink with the inputted text.
function onEdit(e) {
const sheetNames = ["Sheet1", "Sheet2",,,]; // Please set the sheet names you want to run the script.
const column = 5; // Column E. From your question, this script run for the column "E".
const {range} = e;
const sheet = range.getSheet();
const baseUrl = "https://demo.atlassian.net/browse/";
if (!sheetNames.includes(sheet.getSheetName()) || range.columnStart != column) return;
const values = range.getValues().map(([e]) => [SpreadsheetApp.newRichTextValue().setText(e).setLinkUrl(baseUrl + e).build()]);
range.setRichTextValues(values);
}
If you want to run the script for all sheets, you can use the following script.
function onEdit(e) {
const column = 5; // Column E. From your question, this script run for the column "E".
const {range} = e;
const sheet = range.getSheet();
const baseUrl = "https://demo.atlassian.net/browse/";
if (range.columnStart != column) return;
const values = range.getValues().map(([e]) => [SpreadsheetApp.newRichTextValue().setText(e).setLinkUrl(baseUrl + e).build()]);
range.setRichTextValues(values);
}
Added 2:
If you want to run the script to the column "E" of all sheets by one script running, you can also use the following script.
Sample script:
This sample script runs for the specific sheets.
function myFunction() {
const sheetNames = ["Sheet1", "Sheet2",,,]; // Please set sheet names you want to run the script.
const baseUrl = "https://demo.atlassian.net/browse/";
SpreadsheetApp.getActiveSpreadsheet().getSheets().forEach(sheet => {
if (!sheetNames.includes(sheet.getSheetName())) return;
const range = sheet.getRange("E1:E" + sheet.getLastRow());
const values = range.getValues().map(([e]) => [SpreadsheetApp.newRichTextValue().setText(e).setLinkUrl(baseUrl + e).build()]);
range.setRichTextValues(values);
});
}
This sample script runs for all sheets.
function myFunction() {
const baseUrl = "https://demo.atlassian.net/browse/";
SpreadsheetApp.getActiveSpreadsheet().getSheets().forEach(sheet => {
const range = sheet.getRange("E1:E" + sheet.getLastRow());
const values = range.getValues().map(([e]) => [SpreadsheetApp.newRichTextValue().setText(e).setLinkUrl(baseUrl + e).build()]);
range.setRichTextValues(values);
});
}
Are there any way to choose some content in the Google Document Table and copy to the Google Spreadsheet by the Google App Script
Following with my photo idea
that I would like to copy some content in the red box / blue box to the Google Spreadsheet including with the data in column name : level , Due Date 1, Due Date 2
I've started with the following code outline:
function Tables() {
var doc = DocumentApp.getActiveDocument().getBody();
var tables = doc.getTables()[1];
for (var i = 0; i < tables.getNumRows(); ++i) {
var cell = tables.getRow(i);
var text =cell.getText();
Logger.log(text);
}
}
Although I cannot see your sample Spreadsheet, from your sample Google Document and sample output image, I believe your goal as follows.
You want to retrieve the values from the 1st table in Google Document and put the values to Google Spreadsheet by converting the values as follows.
From
To
Modification points:
In your script, 2nd table is retrieved. In your sample Document, an error occurs.
In your case, I think that it is required to retrieve the values from each cell. But in your script, the values are directly retrieved from the rows.
In your script, the values are only retrieved from the rows. In order to achieve your goal, it is required to convert the retrieved values from Document for putting to Spreadsheet.
When above points are reflected to a script, it becomes as follows.
Modified script:
Please copy and paste the following script to the script editor and set the variables and run the script. About the variable of excludeTexts, in this case, these values are from your sample Google Document. When you change the exclude text line in the table of Document, please modify the values.
function myFunction() {
const documentId = "###"; // Please set Document ID.
const spreadsheetId = "###"; // Please set Spreadsheet ID of the destination Spreadsheet.
const sheetName = "Sheet1"; // Please set the sheet name of the destination sheet.
const excludeTexts = ["Part A:", "Part B:", "Part C:"]; // Please set the exclude texts.
// 1. Retrieve values from 1st table from Document and create an array for putting to Spreadsheet.
// const body = DocumentApp.getActiveDocument().getBody(); // If you copy and paste the script to the container-bound script of Document, you can use this line instead of "DocumentApp.openById(documentId).getBody()".
const body = DocumentApp.openById(documentId).getBody();
const table = body.getTables()[0];
let values = [];
for (let r = 0; r < table.getNumRows(); r++) {
const cell = table.getRow(r);
const row = [];
for (let c = 0; c < cell.getNumCells(); c++) {
const text = cell.getCell(c).getText().trim();
row.push(r > 0 && c == 1 ? text.split("\n").map(e => e.trim()).filter(e => !excludeTexts.includes(e)) : text);
}
values = values.concat(Array.isArray(row[1]) ? row[1].map((e, i) => i == 0 ? [row[0], e, ...row.slice(2)] : ["",e,...Array(row.slice(2).length).fill("")]) : [row]);
}
console.log(values)
// 2. Put the created array to Spreadsheet.
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
When above script is run for your Google Document, the sample situation at the top images is obtained.
Note:
This sample script can be used for your sample Google Document. If the structure of your Document is changed, the script might be required to be modified. So please be careful this. When you test this script, please use your sample Google Document.
References:
getRow(rowIndex)
getCell(cellIndex)
I'm trying to Unlink all hyperlinks in a Google Spreadsheet, so far I'm trying to do a search and replace which is the code below, but wondering if there is a specific function to do the unlink?
function replacelinks(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Links");
var values = sheet.getDataRange().getValues();
replaceInSheet(values, '.com', '');
replaceInSheet(values, '.net', '');
I believe your goal as follows.
You want to remove all hyperlinks on a sheet in a Google Spreadsheet using Google Apps Script.
For this, how about this answer?
Modification points:
Unfortunately, in the current stage, it seems that there are no methods for directly removing the hyperlinks of the cells and texts. So in order to achieve your goal, I would like to propose a workaround. The flow of this workaround is as follows.
Copy the sheet you want to remove the hyperlinks in the Google Spreadsheet as a temporal sheet.
Retrieve the richTextValues from the data range of the source sheet.
Retrieve the cell coordinates, which have the hyperlinks, and create an object for using the method of batchUpdate in Sheets API.
Request to the batchUpdate method using the created object.
The cells with the hyperlinks on the source sheet are cleared, and the values of the same coordinates are copied from the temporal sheet to the source sheet. By this, the hyperlinks are removed.
Sample script:
Please copy and paste the following script to the script editor. And, please enable Sheets API at Advanced Google services. And please set the sheet name you want to remove the hyperlinks.
function myFunction() {
const sheetName = "Sheet1"; // Please set the sheet name.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(sheetName);
const sheetId = sheet.getSheetId();
const range = sheet.getDataRange();
const temp = ss.insertSheet();
const tempId = temp.getSheetId();
range.copyTo(temp.getRange("A1"), {contentsOnly: true});
const requests = range.getRichTextValues().reduce((ar, row, i) => {
row.forEach((col, j) => {
const runs = col.getRuns();
if (col.getLinkUrl() || (runs && runs.some(e => e.getLinkUrl()))) {
const req1 = {updateCells:{range:{sheetId:sheetId,startRowIndex:i,endRowIndex:i + 1,startColumnIndex:j,endColumnIndex:j + 1},fields:"userEnteredValue"}};
const req2 = {copyPaste:{
source:{sheetId:tempId,startRowIndex:i,endRowIndex:i + 1,startColumnIndex:j,endColumnIndex:j + 1},
destination:{sheetId:sheetId,startRowIndex:i,endRowIndex:i + 1,startColumnIndex:j,endColumnIndex:j + 1},
pasteType:"PASTE_NORMAL"
}};
ar = ar.concat(req1, req2);
}
});
return ar;
}, []);
Sheets.Spreadsheets.batchUpdate({requests: requests}, ss.getId());
ss.deleteSheet(temp);
}
In this script, the hyperlinks of both with and without HYPERLINK() can be removed.
Note:
In the current stage, it seems that getRichTextValues() cannot retrieve the number values. By this, when the number values has the hyperlinks, these hyperlinks cannot be removed. About this issue, I have already reported to the issue tracker. Ref So when this issue was removed, I think that using above script, all hyperlinks might be be able to be removed. Or, in the current stage, the method of getLinkUrl() used in above script is not included in the official document. So I also think that the method for directly removing the hyperlinks might be added in the future update.
References:
getRichTextValues()
Advanced Google services
Method: spreadsheets.batchUpdate
UpdateCellsRequest
CopyPasteRequest
What helped for me was to setShowHyperlink to false for the range.
Example:
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getActiveSheet();
const range = ws.getRange(lastRow, 1)
range.setValue('https://example.com');
range.setShowHyperlink(false);
But as soon as you double click such a cell, Google will re-apply the hyperlink.