Hi I'm trying to copy certain range of cells from google sheet to gmail using script. But it is not working especially the format is changing. How can I copy like 'ctrl+c->ctrl+v' using script? here is my code
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet(); //access to the spreadsheet
SpreadsheetApp.setActiveSheet(sheet.getSheetByName('MAIL')); //access to the sheet by name
var range = sheet.getRange('C7:I23'); //assign the range you want to copy
var copy = range.getValues();
var sh = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(sh.getSheetByName('MAIL'));
var data = sh.getRange("C7:I23").getValues();
var htmltable =[];
//var TABLEFORMAT-> // i want this format just like i made on spread sheet
//var htmltable = '<table ' +TABLEFORMAT+' ">';
for (row = 0; row<data.length; row++){
htmltable += '<tr>';
for (col = 0 ;col<data[row].length; col++){
if (data[row][col] === "" || 0) {
htmltable += '<td>' + ' ' +'</td>';
}
else if (row === 0) {
htmltable += '<th>' + data[row][col] + '</th>';
}
else {
htmltable += '<td>' + data[row][col] + '</td>';
}
}
htmltable += '</tr>';
}
htmltable += '</table>';
Logger.log(data);
Logger.log(htmltable);
var email_subject = "";
var my_email = "mail";
MailApp.sendEmail({
to: my_email,
subject: email_subject,
htmlBody: htmltable,
})}
Related
I have a bunch of tables with Id int primary keys. However, I forgot to set AutoNum to True in the UI. Since changing all hundreds of tables is tedious, how can I set this property for all Id columns?
I have built a script that runs through each table and detects the Id column:
var package as EA.Package;
package = Repository.GetTreeSelectedPackage();
var tablesEnumerator = new Enumerator(package.Elements);
while (!tablesEnumerator.atEnd()) {
var table as EA.Element;
table = tablesEnumerator.item();
var methodsEnumerator = new Enumerator(table.Methods);
while (!methodsEnumerator.atEnd()) {
var method as EA.Method;
method = methodsEnumerator.item();
if (method.Name !== "Id") { continue; }
Session.Output(method.Name);
// Now what?!
}
}
I have searched for AutoNum in EnterpriseArchitect docs and APIs, but was unable to find suitable references.
According to Autonum in Column Properties inaccessible you can actually change the AutoNum behaviour via API with the means of TaggedValues. So there is no need of direct SQL updates to the database.
Setting the tagged values property and AutoNum on the Id attribute (not the method of the table seems to do the magic. It tried it via the builtin script engine and it works:
Before running the script
After running the script
The update script
!INC Local Scripts.EAConstants-JScript
function main()
{
var package = Repository.GetTreeSelectedPackage();
var elements as EA.Collection;
elements = package.Elements;
Session.Output("Elements Count " + elements.Count);
for ( var ec = 0 ; ec < elements.Count ; ec++ )
{
var element as EA.Element;
element = elements.GetAt(ec);
if("Table" != element.MetaType) continue;
Session.Output("Element: Name '" + element.Name + "' [" + element.ElementGUID + "] '" + element.MetaType + "'.");
var attributes as EA.Collection;
attributes = element.Attributes;
for ( var ac = 0; ac < attributes.Count ; ac++)
{
var attribute as EA.Attribute;
attribute = attributes.GetAt(ac);
if("Id" != attribute.Name) continue;
Session.Output("Attribute: Name '" + attribute.Name + "' [" + attribute.AttributeGUID + "] in element '"+ element.Name + "' [" + element.MetaType + "].");
var hasTvProperty = false;
var hasTvAutonum = false;
var taggedValues as EA.Collection;
taggedValues = attribute.TaggedValues;
Session.Output("TaggedValues: Count " + taggedValues.Count);
for ( var tc = 0; tc < taggedValues.Count; tc++)
{
var taggedValue as EA.TaggedValue;
taggedValue = taggedValues.GetAt(tc);
if("property" != taggedValue.Name && "AutoNum" != taggedValue.Name) continue;
Session.Output("TaggedValue: Name '" + taggedValue.Name + "'. Value '" + taggedValue.Value + "'");
if("property" != taggedValue.Name)
{
taggedValue.Value = "AutoNum=1;StartNum=1;Increment=1;";
taggedValue.Update();
element.Update();
hasTvProperty = true;
}
if("AutoNum" != taggedValue.Name)
{
taggedValue.Value = "True";
taggedValue.Update();
element.Update();
hasTvAutonum = true;
}
}
if(!hasTvProperty)
{
var tv = taggedValues.AddNew("property", "AutoNum=1;StartNum=1;Increment=1;");
tv.Update();
element.Update();
}
if(!hasTvAutonum)
{
var tv = taggedValues.AddNew("AutoNum", "True");
tv.Update();
element.Update();
}
break;
}
}
}
main();
Content of the t_attributetags table
I have a script that forwards all of my emails that come in during specific times to email#domain.com.
The problem I am having, is that sometimes email#domain.com sends me an email during that time.
Can anyone suggest a way to add a rule that it should forward to all addresses except forwarding address?
function forwardEmails() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var settings = ss.getSheetByName('Settings').getDataRange().getValues();
if (settings[1][1] == 'No')
return;
if (settings[2][1] == "")
throw new Error('Please set Forward Email!');
var email = PropertiesService.getScriptProperties().getProperty('email');
if (!email)
throw new Error('First authorize script by clicking on menu: Email Forwarder >> Authorize Script');
var today = (new Date());
var applicableRules = validRules(today);
if (applicableRules) {
var unread = GmailApp.getInboxUnreadCount();
if (!unread)
return;
var threads = GmailApp.getInboxThreads(0, unread>100?100:unread);
var cutOff = today.getTime() - (MINUTES*60*1000 + 100); // 10 mins + 100 ms
for (var i=0; i<threads.length; i++) {
var msgs = threads[i].getMessages();
for (var j=0; j<msgs.length; j++) {
var from = msgs[j].getFrom();
var msgDate = msgs[j].getDate();
var msgTime = (new Date(msgDate)).getTime();
var diff1 = msgTime - cutOff;
if (diff1 > 0 && from.indexOf(email) == -1) {
var to = msgs[j].getTo();
var subject = msgs[j].getSubject();
var attach = msgs[j].getAttachments();
var body = msgs[j].getBody();
var plainBody = msgs[j].getPlainBody();
var replyTo = msgs[j].getReplyTo();
var options = {replyTo: from};
if (attach.length > 0)
options.attachment = attach;
GmailApp.sendEmail(settings[2][1], subject, plainBody, options );
}
}
}
}
} catch (error) {
var html = '<p>'+ error + '</p><br><br>Email Forwarder Rules & Settings<p>Line: '+ error.lineNumber + ', Filename: ' + error.fileName + '</p>';
if (!email)
email = Session.getActiveUser().getEmail();
MailApp.sendEmail(email, 'Email Forwarder Script Failed!', error + '\n\nEmail Forwarder Rules & Settings URL: ' + ss.getUrl(), {htmlBody: html});
}
}
Instead of using getInboxThreads() use search().
getInboxThreads() will return threads in your inbox while search() will return those that meet the search query. The following query will include include messages in your inbox but exclude those from email#domain.com
in:inbox -from:email#domain.com
You could add a check in the second loop of the "forwardEmails" function. The code below would skip any unread emails which have arrived from the forwarding address (I'm assuming the forwarding email is referenced in "settings[2][1]".
for (var i=0; i<threads.length; i++) {
var msgs = threads[i].getMessages();
for (var j=0; j<msgs.length; j++) {
var from = msgs[j].getFrom();
var msgDate = msgs[j].getDate();
var msgTime = (new Date(msgDate)).getTime();
var diff1 = msgTime - cutOff;
// New code
if (from === settings[2][1]) {
continue;
}
I'm still very new to scripting and can't work out why the below script doesn't work
function sendReturnEmail(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
if(event.range.getA1Notation().indexOf("K") && sheet.getRange("K" + row).getDisplayValue() == "Approved")
{
var rowVals = getActiveRowValues(sheet);
var aliases = GmailApp.getAliases();
var to = rowVals.user;
var subject = "Allocation request approved";
var body = "Your allocation request of " +rowVals.quantity + " cases on " + rowVals.date + " from " + rowVals.depot + " has been approved. <br \> <br \>"
+ "Regards, <br \> <br \>" +rowVals.analyst + "<br \> CPF Team";
Logger.log(aliases);
GmailApp.sendEmail(to,subject,body,
{from: aliases[0]})
;
}}
function getActiveRowValues(sheet){
var cellRow = sheet.getActiveRange().getRow();
// get depot value
var depotCell = sheet.getRange("E" + cellRow);
var depot = depotCell.getDisplayValue();
// get date value
var dateCell = sheet.getRange("F" + cellRow);
var date = dateCell.getDisplayValue();
// get quantity value
var quantCell = sheet.getRange("G" + cellRow);
var quant = quantCell.getDisplayValue();
// return an object with your values
var analystCell = sheet.getRange("J" + cellRow);
var analyst = analystCell.getDisplayValue();
var userCell = sheet.getRange("O" + cellRow);
var user = userCell.getDisplayValue();
return {
depot: depot,
date: date,
quantity: quant,
analyst: analyst,
user: user
} }
}
The sheet is question has several scripts running in it, one of them being this:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Allocation Requests" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 2) { //checks the column
var nextCell = r.offset(0, 13);
nextCell.setValue(Session.getEffectiveUser());
}
}
I now want the sheet to send an email to the email address captured using the above script (which works fine) when the corresponding cell in column K is manually changed to "Approved."
Can anyone see what I'm doing wrong. I get no errors when it runs, but I'm not getting an email. I've searched other questions but none have helped. Many thanks in advance.
My query relates to this Google Form responses spreadsheet. I'm trying to adapt the script I got from here.
function cleanup() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form responses 1');
var values = sheet.getDataRange().getValues();
var InAYear = (Date.now()/86400000 + 25569) + 365;
for (var i = values.length - 1; i >= 0; i--) {
if ( values[i][5] >= InAYear) {
sheet.deleteRow(i+1);
}
}
}
I'm trying to get this to compare the date in the Start Date column of the sheet with the date in a year from now and delete the row if the column entry is greater than this (ie. if the date on the sheet is more than a year in advance). However, I obviously don't understand how to get the two different dates in the same format because examining variable values when debugging shows wildly different values.
Try the following script code:
function cleanup() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Form responses 1');
var values = sheet.getDataRange().getValues();
var today = Utilities.formatDate(new Date(), ss.getSpreadsheetTimeZone(), 'MM/dd/yyyy')
for (var i = values.length - 1; i >= 0; i--) {
if ( values[i][4] != '' && dateDiffInDays(values[i][4],today) > 365 ) {
sheet.deleteRow(i+1);
}
}
};
function dateDiffInDays(d1,d2) {
var date1 = new Date(d1);
var date2 = new Date(d2);
var timeDiff = date1.getTime() - date2.getTime();
return Math.ceil(timeDiff / (1000 * 3600 * 24));
};
It looks like I have it working, and sending me an email.
function cleanup(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Form responses 1');
var values = sheet.getDataRange().getValues();
var today = new Date();
var InAYear = new Date();
InAYear.setFullYear( today.getFullYear()+1 );
var emailaddress = "****";
var subject = "Annual Leave Request";
var message = "Annual Leave has been requested as follows:" + "\n\n";
for (var i = values.length - 1; i >= 0; i--) {
if ( values[i][4] > InAYear ) {
sheet.deleteRow(i+1);
subject = "Annual Leave Request - Rejected";
message = "The following annual leave request was rejected due to being more than one year in advance:" + "\n\n";
}
}
for(var field in e.namedValues) {
message += field + ':'
+ "\n" + e.namedValues[field].toString() + "\n\n";
}
MailApp.sendEmail(emailaddress, subject, message);
}
Thank you to Kishan, without who's help I would not have been able to get to this stage.
I want to run a function that updates some values when I edit one cell of a column. This line of the trigger works well: dataCell0.setValue(today_date(new Date())[2]);. But this other line updatePercent(); doesn't. But if I call this updatePercent() function from a time based trigger (in Resources), it works well. What is going wrong with this updatePercent() call?
function onEdit(){
var s = SpreadsheetApp.getActiveSheet();
if( ( s.getName() == "mySheet1" ) || (s.getName() == "mySheet2") ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( s.getRange(1, r.getColumn()).getValue() == "PORCENT_TIME") { // If you type a porcent, it adds its date.
var dataCell0 = r.offset(0, 1);
dataCell0.setValue(today_date(new Date())[2]);
updatePercent();
}
}
}
Here the updatePercent function code:
/**
* A function to update percent values accoding to input date.
**/
function updatePercent() {
var sheet = SpreadsheetApp.getActiveSheet();
var column = getColumnNrByName(sheet, "PORCENT_TIME");
var input = sheet.getRange(2, column+1, sheet.getLastRow(), 4).getValues();
var output = [];
for (var i = 0; i < input.length; i++) {
var fulfilledPercent = input[i][0];
Logger.log("fulfilledPercent = " + fulfilledPercent);
var finalDate = input[i][3];
Logger.log("finalDate = " + input[i][3]);
if ( (typeof fulfilledPercent == "number") && (finalDate instanceof Date) ) {
var inputDate = input[i][1]; // Date when input was added.
var restPorcentPen = 100 - fulfilledPercent;
var restantDays = dataDiff(inputDate, finalDate);
var percentDay = restPorcentPen/restantDays;
Logger.log("percentDay = " + percentDay);
var passedTime = dataDiff(inputDate, new Date());
Logger.log("passedTime = " + passedTime);
var passedPorcent = passedTime * percentDay; // How much percent this passed time is?
Logger.log("passedPorcent = " + passedPorcent);
var newPorcent = (fulfilledPercent + passedPorcent);
newPorcent = Math.round(newPorcent * 100) / 100;
Logger.log("newPorcent = " + newPorcent);
var newInputDate = hoje_data(new Date())[2]; // Now update the new input date
// newPorcent = newPorcent.toFixed(2);
output.push([newPorcent, newInputDate]);
sheet.getRange(2, column+1, output.length, 2).setValues(output);
Logger.log(" ");
var column25Dec = getColumnNrByName(sheet, "PORCENT_25DEZ");
var passedTimeSince25Dec = dataDiff(new Date(2013,11,25), new Date()); // Months: January is 0;
var decPercent = (newPorcent - (passedTimeSince25Dec * percentDay)); // .toFixed(2).replace(".", ",");
decPercent = Math.round(decPercent * 100) / 100;
// if (sheet.getRange(output.length+1, column25Dec+1).getValues() == ''){
sheet.getRange(output.length+1, column25Dec+1).setValue(decPercent );
// }
var remainingYears = dataDiffYears(new Date(), finalDate);
sheet.getRange(output.length+1, column).setValue(remainingYears);
}
else {
newPorcent = "Put a final date"
output.push([newPorcent, inputDate]);
sheet.getRange(2, column+1, output.length, 2).setValues(output);
}
if (finalDate instanceof Date){
var remainingYears = dataDiffYears(new Date(), finalDate);
// Logger.log("remainingYears = " + remainingYears);
}
else {
remainingYears = "insert a valid date";
}
sheet.getRange(output.length+1, column).setValue(remainingYears);
}
}
I will guess you're using the new gSheets. Check if it will work in the old-style sheets. The new sheets' onEdit trigger has problems, particularly with getActive.
My problem was in the updatePercent() funciton. Thank you, guys!