Trying to replace text + date just by date using regex, but it not works:
function myfunction() {
var SourceFolder = DriveApp.getFolderById("");
var Files = SourceFolder.getFiles()
var body = DocumentApp.getActiveDocument().getBody();
while(Files.hasNext()) {
var file = Files.next();
body.replaceText("Date: \d{2}.\d{2}.\d{4}", "31.10.2020")
}
}
Thanks
In your code, var body = DocumentApp.getActiveDocument().getBody(); is declared outside of the loop, so you always refer to the active document body in your while loop.
You may use
while(Files.hasNext()) {
var file = Files.next();
var doc = DocumentApp.openById(file.getId());
var body = doc.getBody();
body.replaceText("Date: \\d{2}\\.\\d{2}\\.\\d{4}", "31.10.2020")
}
The point here is to use double backslashes in the pattern, and escape the dot chars since otherwise a . matches any char but a line break char.
function replace_text() {
// Get speadshhet with ID
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// Returns cell with ID (User will insert his or her folder ID in cell B3)
var range = sheet.getRange(3, 2);
var values = range.getDisplayValue();
// Get folder by ID - insert your folder ID
var SourceFolder = DriveApp.getFolderById(values);
// Iterate throw all files in folder
var Files = SourceFolder.getFiles();
while(Files.hasNext()) {
var file = Files.next();
// Get all documents ID
var doc = DocumentApp.openById(file.getId());
// Get text body to replace
var body = doc.getBody();
// Insert header in document + alignment
var header = body.insertParagraph(0, 'TEXT');
header.setAlignment(DocumentApp.HorizontalAlignment.RIGHT)
// Text style
var style = {};
//style[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.RIGHT;
style[DocumentApp.Attribute.FONT_FAMILY] = 'Arial';
style[DocumentApp.Attribute.FONT_SIZE] = 9;
style[DocumentApp.Attribute.FOREGROUND_COLOR] = '#000000';
body.setAttributes(style)
Logger.log(body)
// Replacing text
body.replaceText("Text", " ");
body.replaceText("Date:\\s*\\d{2}\\.\\d{2}\\.\\d{4}", "31.10.2020")
var paragraphs = body.getParagraphs();
for (var i = 7; i < paragraphs.length; i++) {
var paragraph = paragraphs[i];
paragraph.setAlignment(DocumentApp.Horizontal`enter code here`Alignment.LEFT)
}
}
}
Related
Hello and thanks in advance for your help,
I find many other topics about this, but I did not find answers to my problem, so here I am.
My goal is to automaticly create dropdow lists in a board (between 50-100 drop down list), according to a word in another column. The data should be in another spreadsheet, and most of the dropdown list could go around 600-700 items.
Please check in picture below for more explainations :
board picture
The dropdown list 1 and 2 are created in column G and H if it does find a sheet name in the first word of the column F "designation". If you pick an item of colum G "Libellés", it makes a Vlookup for column "MP" and price in the designated sheet. Same if you pick an item in of column "MP", it makes a Vlookup in "Libellés" and "price" to match.
This is working fine when all sheets are in the same spreadsheet, but I can't find a way to make it work when all data sheets are in another spreadsheet. The spreadsheet with the code will be copy many times (200+ each year), so I want to put the database sheets (15000+lignes x 5 columns) in only one spreadsheet that feeds all others "small" spreadsheets when we open those.
I tryed many options :
requireValueInList : This is not working, some lists are 600-700 items, not working with big lists like this.
list from a range : Ranges are too big, and I have around 50-100 dropdown list of 100-700 items, this is too much, program stops before the end (and I have a good computer, which is not the case of most of my colleagues), so this is not a solution, or I am doing it wrong.
requireValueInRange : This is what I am using to make it run when everything is on the same spreadsheet, but can't use it if datas are on another spreadsheet.
Is there a way to get around requireValueInRange limitation? This is the first time I use google app script so please don't judge too harshly.
here is the code, it is working fine when all data sheets are in the same sspreadsheet as the target sheet for drop dow list:
function onOpen(e) {
// sss for source spreadsheet where I have all datas, and tss for target spreadsheet where I want my lists to be created
var sss1 = spreadsheetApp.openById('blahblah');
var ssh1 = sss1.getSheetByName('Emballages');
var tss = SpreadsheetApp.getActiveSpreadsheet();
var tsh = tss.getActiveSheet();
var tsh1 = tss.getSheetByName('Fiche_eclate_CS');
// The below part is to update 2 lists, using datas from the sheet "emballages" in the source spreadsheet, all working fine except data validation rule, won't accept arguments
var sheet = tss.getSheets()[0];
var column = sheet.getRange("F:F").getValues();
var prow;
for (var i = 0; i < column.length; i++){
if (column[i][0] === "Packaging :") {
prow = i+1;
break;
}
}
var emblrow = ssh1.getRange('B:B').getLastRow();
var cel1D = tsh1.getRange(prow,7);
// This is where I have problems. The call ('B2:B'+ emblrow) is not accepted. I can't use this as data validation on another spreadsheet.
var cel2D = ssh1.getRange('B2:B'+ emblrow);
var ruleD = SpreadsheetApp.newDataValidation().requireValueInRange(cel2D).build();
cel1D.setDataValidation(ruleD);
var cel1M = tsh1.getRange(prow,8);
// Same problem here. The call ('A2:A'+ emblrow) is not accepted.
var cel2M = ssh1.getRange('A2:A'+ emblrow );
var ruleM = SpreadsheetApp.newDataValidation().requireValueInRange(cel2M).build();
cel1M.setDataValidation(ruleM);
// The below part is to update many lists, using datas from one sheet in the source spreadsheet. To find the good sheet in the other spreadsheet, I use the split function. This part is working fine. I only have problems with data validation rules, same as above.
var ui = SpreadsheetApp.getUi();
var button = ui.alert("Voulez vous mettre à jour toutes les listes de la feuille ?",ui.ButtonSet.YES_NO);
if (button == ui.Button.YES) {
var anchhrow;
var anchbrow;
var column1 = tsh1.getRange("B:B").getValues();
for (var i = 0; i < column1.length; i++){
if (column1[i][0] === "Anchor-haut") {
anchhrow = i+3;
break;
}
}
for (var i = 0; i < column1.length; i++){
if (column1[i][0] === "Anchor-bas") {
anchbrow = i;
break;
}
}
var rangeH1 = tsh.getRange('H'+anchhrow +':H'+anchbrow).getValues();
var range = tsh.getRange('H'+anchhrow +':H'+anchbrow);
var lrowH = rangeH1.length;
for (var k=0; k<lrowH; k++){
var rown = anchhrow + k;
var testrng = sheet.getRange("F" + rown);
if ( testrng == "" ) {
}
else {
var name = nom(tsh,rown);
var ssh3 = sss1.getSheetByName(name);
if (ssh3 == null){
}
else {
var flrow = ssh3.getRange('B2:B').getLastRow();
var rng1D = tsh1.getRange(k+anchhrow,7);
// same issu, can't use ('B2:B'+ flrow)for data validation
var rng2D = ssh3.getRange('B2:B'+ flrow);
var ruleD =
SpreadsheetApp.newDataValidation().requireValueInRange(rng2D).build();
rng1D.setDataValidation(ruleD);
var rng1M = tsh1.getRange(k+anchhrow,8);
// same here, can't use ('A2:A'+ flrow)for data validation
var rng2M = ssh3.getRange('A2:A'+ flrow );
var ruleM = SpreadsheetApp.newDataValidation().requireValueInRange(rng2M).build();
rng1M.setDataValidation(ruleM);
}
}
}
function nom(sheet,row){
var word = [{}];
var rng = sheet.getRange("F" + row);
var word = rng.getValue().split(" ");
Logger.log(word);
return word[0];
}
}
else {
}
// This part is where I control prices once all lists are updated, this is working fine.
var ui = SpreadsheetApp.getUi();
var button = ui.alert("Les listes ont été mises à jour. Voulez vous mettre à jour les prix ?",ui.ButtonSet.YES_NO);
if (button == ui.Button.YES) {
for(var j=0;j<lrowH; j++){
var cellI1 = tsh.getRange(j+anchhrow,8).getValue();
if (cellI1 == "") {
}
else {
var cellI2 = vlookup(ssh2,1,3,cellI1);
tsh.getRange(j+anchhrow,9).setValue(cellI2);
function vlookup(sheet, column, index, value) {
var lastRow=sheet.getLastRow();
var data=sheet.getRange(1,column,lastRow,column+index).getValues();
for(i=0;i<data.length;++i){
if (data[i][0]==value){
return data[i][index];
}
}
}
}
}
}
else {
}
Browser.msgBox ("MAJ feuille terminée");
}
Feel free to ask questions if there are stuffs you don't understand or if you need more details.
Thanks in advance,
The main issue you are encountering is due to the fact that you are calling the getActiveSpreadsheet method instead of the openById(id).
However, assuming that you have the same names for the sheets but they're just in different spreadsheets and you want to keep on using the requireValueInRange method, I suggest you add the following lines to your code:
Code
function createDataValidation() {
let spreadsheetIds = ['SS_1_ID', 'SS_2_ID', ...];
for (let i=0; i<spreadsheetIds.length; i++) {
var tss = SpreadsheetApp.openById(spreadsheetIds[i]);
var tsh = tss.getActiveSheet();
var tsh1 = tss.getSheetByName('Fiche_eclate_CS');
// the rest of your code
}
}
The code above is looping through all the spreadsheets - this is done by storing all the ids of the spreadsheets you want to use in the spreadsheetIds variable and afterwards, by using a for loop, is accessing each one of them and using the code you already have.
Reference
Apps Script SpreadsheetApp Class - openById.
I suggest
function betweenSpreadsheets() {
let localSs = SpreadsheetApp.getActiveSpreadsheet();
let distSsUrl = 'https://docs.google.com/spreadsheets/d/1H-Zh blah blah KHP7x8/edit?usp=sharing';
let distSsId = '1H-Zh blah blah KHP7x8';
let distSs1 = SpreadsheetApp.openById(distSsId)
let distSs2 = SpreadsheetApp.openByUrl(distSsUrl)
}
Then proceed as if the sheets were in the same spreadsheet.
I'm using the below code in order to display a photo in slide show, i need to display: name,job and quote for each person, but actually only photos change on time interval specified ...can anyone help?
var img1 = document.getElementById("img1");
var testname = document.getElementById("testname");
var testjob = document.getElementById("testjob");
var testpa = document.getElementById("testpa");
var currentPos = 0;
var images = ["ch1.jpg", "ch2.jpg", "ch3.jpg"]
var testname = [“John Smith” ,”Jan Rosso”,”Raphael Matthew”]
var testjob = [“Manager” ,”Director”,”Supervisor”]
var testpa = [“I like this company”,”It’s amazing”,”Wondeful atmospher”]
function volgendefoto() {
if (++currentPos >= images.length)
currentPos = 0;
img1.src = images[currentPos];
testname.value = testname[currentPos];
testjob.value = testjob[currentPos];
testpa.value = testpa[currentPos];
}
setInterval(volgendefoto, 3000);
function test(){
document.getElementById('text').value=document.getElementById('testname').value
}
testName and the others may need to be updated via innerHTML
function volgendefoto() {
if (++currentPos >= images.length)
currentPos = 0;
img1.src = images[currentPos];
testname.innerHtml = testname[currentPos];
testjob.innerHtml = testjob[currentPos];
testpa.innerHtml = testpa[currentPos];
}
Someone please help.
I am trying to create a simple script which records button presses in order.
I have:
function P1Buzzer() {
var sheet = SpreadsheetApp.getActiveSheet();
var row = 6;
var col = 1;
var Name = sheet.getRange(row, col).getValue();
var sheet = SpreadsheetApp.getActiveSheet();
var row = 192;
var col = 1;
var AnswerPosition = sheet.getRange(row, col).getValue();
if (AnswerPosition = 1) {
sheet.getRange(199, 1).setValue(Name);
var AnswerPosition = AnswerPosition + 1
sheet.getRange(192, 1).setValue(AnswerPosition);
}
if (AnswerPosition = 2) {
sheet.getRange(200, 1).setValue(Name);
var AnswerPosition = AnswerPosition + 1
sheet.getRange(192, 1).setValue(AnswerPosition);
}
}
The problem I have is that when I run the script it does both the commands, ignoring the if command.
Any ideas?
First, you are setting the value to 1 by using = instead of ==. Second, if it was 1, you add one to it and then check to see if it is 2. I'll bet it is!
if (AnswerPosition == 1) {
sheet.getRange(199, 1).setValue(Name);
var AnswerPosition = AnswerPosition + 1
sheet.getRange(192, 1).setValue(AnswerPosition);
} else if (AnswerPosition == 2) {
...
I am writing a function that will search a spreadsheet for days an employee has worked hours, create an array with the values for job number, job name, employee name, hours, and date, and then put them onto another spreadsheet. It also only shows hours that were within the past 8 days so that time can be worked out for the week when we have to report hours (I'm scheduling it to run the day time is due). I also have been filtering out days with blank hours, which limits the amount of data that gets copied over.
I am encountering an issue where on one employee the function to skip the blank hours does not work. For other employees I have been able to use "" to indicate an empty cell. I have also tried to use (null) as a value, but that only ignores 6 of 7 days (It still logs days with no hours that are adjacent to cells that calculate hours in the week).
What I can't figure out is why this doesn't work on just one sheet out of the whole Google Sheets document. I have simplified my spreadsheet to reduce personal information, and to make it easier to parse the script, but in my original document I track 6 employees with similar code, and only one is showing this issue.
https://docs.google.com/spreadsheets/d/1ve0EPVQJ2vmWG1NYHMncw1ZljP3yXd28dMeNC38Jiy4/edit?usp=sharing
Is a link to the spreadsheet. Code is below.
function shoptime(){
var ss = SpreadsheetApp.getActive().getId();
var stephensheet = Sheets.Spreadsheets.Values.get(ss, 'Stephen!A2:G');
var tiffanysheet = Sheets.Spreadsheets.Values.get(ss, 'Tiffany!A2:G');
var scripts = SpreadsheetApp.getActive().getSheetByName("Scripts");
var currentDate = new Date();
var pastweek = new Date();
pastweek.setDate(currentDate.getDate() -8);
var array=[];
for (var a = 0; a < stephensheet.values.length; a++){
var jobdate = stephensheet.values[a][1];
var intime = stephensheet.values[a][2];
var outtime = stephensheet.values[a][3];
var dailyhours = stephensheet.values[a][4];
if (new Date(jobdate) > pastweek){
if (dailyhours != (null)){
array.push(["NA","Office","Stephen",dailyhours,jobdate]);
}
}
}
for (var a = 0; a < tiffanysheet.values.length; a++){
var jobdate = tiffanysheet.values[a][1];
var intime = tiffanysheet.values[a][2];
var outtime = tiffanysheet.values[a][3];
var dailyhours = tiffanysheet.values[a][4];
if (new Date(jobdate) > pastweek){
if (dailyhours != ("")){
array.push(["NA","Office","Tiffany",dailyhours,jobdate]);
}
}
}
if(array[0]){
scripts.getRange(scripts.getLastRow()+1,1,array.length,5).setValues(array);
}
SpreadsheetApp.flush();
}
I'm not sure of the exact issue but checking for cells that have a value rather than cells that are not null should work for you.
function shoptime(){
var ss = SpreadsheetApp.getActive().getId();
var stephensheet = Sheets.Spreadsheets.Values.get(ss, 'Stephen!A2:G');
var tiffanysheet = Sheets.Spreadsheets.Values.get(ss, 'Tiffany!A2:G');
var scripts = SpreadsheetApp.getActive().getSheetByName("Scripts");
var currentDate = new Date();
var pastweek = new Date();
pastweek.setDate(currentDate.getDate() -8);
var array=[];
for (var a = 0; a < stephensheet.values.length; a++){
var jobdate = stephensheet.values[a][1];
var intime = stephensheet.values[a][2];
var outtime = stephensheet.values[a][3];
var dailyhours = stephensheet.values[a][4];
if (new Date(jobdate) > pastweek){
if (dailyhours){
array.push(["NA","Office","Stephen",dailyhours,jobdate]);
}
}
}
for (var a = 0; a < tiffanysheet.values.length; a++){
var jobdate = tiffanysheet.values[a][1];
var intime = tiffanysheet.values[a][2];
var outtime = tiffanysheet.values[a][3];
var dailyhours = tiffanysheet.values[a][4];
if (new Date(jobdate) > pastweek){
if (dailyhours){
array.push(["NA","Office","Tiffany",dailyhours,jobdate]);
}
}
}
if(array[0]){
scripts.getRange(scripts.getLastRow()+1,1,array.length,5).setValues(array);
}
SpreadsheetApp.flush();
}
And to modify the code to use the built-in service with is much more straight forward in this case;
function shoptime(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var stephensheet = ss.getSheetByName('Stephen').getDataRange().getValues();
var tiffanysheet = ss.getSheetByName('Tiffany').getDataRange().getValues();
var scripts = ss.getSheetByName("Scripts");
var currentDate = new Date();
var pastweek = new Date();
pastweek.setDate(currentDate.getDate() -8);
var array=[];
for (var a = 0; a < stephensheet.length; a++){
var jobdate = stephensheet[a][1];
var intime = stephensheet[a][2];
var outtime = stephensheet[a][3];
var dailyhours = stephensheet[a][4];
if (new Date(jobdate) > pastweek){
if (dailyhours != ""){
array.push(["NA","Office","Stephen",dailyhours,jobdate]);
}
}
}
for (var a = 0; a < tiffanysheet.length; a++){
var jobdate = tiffanysheet[a][1];
var intime = tiffanysheet[a][2];
var outtime = tiffanysheet[a][3];
var dailyhours = tiffanysheet[a][4];
if (new Date(jobdate) > pastweek){
if (dailyhours != ""){
array.push(["NA","Office","Tiffany",dailyhours,jobdate]);
}
}
}
if(array[0]){
scripts.getRange(scripts.getLastRow()+1,1,array.length,5).setValues(array);
}
SpreadsheetApp.flush();
}
Finally, if you are scraping data from 6 sheets in the exact same format then a another loop and an array of the sheet names will save on repetition of code
function shoptime() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ['Stephen', 'Tiffany'] // add the aditional sheet names here
var scripts = SpreadsheetApp.getActive().getSheetByName("Scripts");
var currentDate = new Date();
var pastweek = new Date();
pastweek.setDate(currentDate.getDate() - 8);
var array = [];
for (var i = 0; i < sheets.length; i++) {
var sheet = ss.getSheetByName(sheets[i]);
var data = sheet.getDataRange().getValues();
for (var a = 0; a < data.length; a++) {
var jobdate = data[a][1];
var intime = data[a][2];
var outtime = data[a][3];
var dailyhours = data[a][4];
if (new Date(jobdate) > pastweek) {
if (dailyhours) {
array.push(["NA", "Office", sheets[i], dailyhours, jobdate]);
}
}
}
}
if (array[0]) {
scripts.getRange(scripts.getLastRow() + 1, 1, array.length, 5).setValues(array);
}
SpreadsheetApp.flush();
}
Within famo.us, I want to place a variable-length wrapping title near the top then have images etc follow. All items must be their own surface as some have click events and animations but all the positioning must be super fast to calculate and place based on the text height and of course must avoid DOM access for the 60fps. This must happen for a series of mini-posts, streaming real time and for infinite scroll.
So far, I came up with an approach that works using an ascii character map to pixel width load off screen on init if isn't already in localStorage. It uses jquery to do the sizing for each character, then determine line height by checking a breaking word and the height of that box. After that I use this map for calculations on the fly so I don't touch DOM again. It seems to work fine but is completely dependent on knowing the style of font going to be used in a very specific way. For each new style, I would have to have a different mapping which sucks.
Is there another approach that is more built in to famo.us?
I'm answering my own question because its frankly been awhile, the new framework is going to come out June 22nd of this month (at the time of the this writing). Just going to put how I'm doing this currently which is the way I described above.
Here's the 0.3.5 way of Famou.us to do this.
This is in a file "utils/lines.js" I whipped up. Hack, yes. Works, yes.
define(function(require) {
'use strict';
var $ = require('jquery');
var cache = require('utils/cache');
function getLineInfo(id) {
var cacheKey = 'lineInfo_' + id;
var savedLineInfo = cache.get(cacheKey);
if (savedLineInfo)
return savedLineInfo;
var charStart = 32; // space
var charEnd = 126; // ~
var $charDump = $('<div>', { id: id });
$('body').append($charDump);
for (var i = charStart; i <= charEnd; i++)
$charDump.append($('<div>', { class: 'char', css: { top: (i-32) * 20 } }).html('&#' + i));
var charMap = {};
$charDump.find('.char').each(function() {
var $this = $(this);
var char = $this.text().charCodeAt(0);
var w = $this.width();
charMap[char] = w;
});
$charDump.html('<div class="line">abc<br>123<br>456</div>');
var lineHeight = $charDump.height() / 3;
$charDump.remove();
savedLineInfo = {
lineHeight: lineHeight,
charMap: charMap
};
cache.set(cacheKey, savedLineInfo);
return savedLineInfo;
}
function getLines(text, width, id, maxLines) {
var lineInfo = getLineInfo(id);
var cleaned = $.trim(text.replace(/\s+/gm, ' '));
var words = cleaned.split(' ');
var lines = 1;
var lineWidth = 0;
var spaceLength = lineInfo.charMap[32];
var allLines = '';
words.forEach(function(word) {
var wordLength = 0;
word.split('').forEach(function(char) {
var charLength = lineInfo.charMap[char.charCodeAt(0)];
if (!charLength)
charLength = spaceLength;
wordLength += charLength;
});
if (lineWidth + wordLength + spaceLength <= width) {
lineWidth += wordLength + spaceLength;
if (maxLines)
allLines += word + ' ';
}
else {
lineWidth = wordLength;
if (maxLines && lines <= maxLines)
allLines += word + ' ';
else if (maxLines)
return {text: allLines.substr(0, allLines.length - 3) + '...', lines: lines};
lines++;
}
});
if (maxLines)
return {text: allLines, lines: lines};
return lines;
}
function getTextHeight(text, width, id, maxLines) {
var lineInfo = getLineInfo(id);
var info;
if (maxLines) {
info = getLines(text, width, id, maxLines);
info.height = lineInfo.lineHeight * info.lines;
return info;
}
return lineInfo.lineHeight * getLines(text, width, id);
}
return {
getLines: getLines,
getLineInfo: getLineInfo,
getTextHeight: getTextHeight
};
});