How to write Google Sheets Script that searches my drive files for a variable search term entered in Cell B1 of my sheet? - google-sheets-api

I'm trying to write a google sheets script to search a series of my Drive files for a variable search term. My code works well as long as I consistently entitle my files that I want to search with "Joshs File". But I want to be able to search fullText by a variable search term entered in cell B1 of my sheet. What syntax do I use to do that?
fullText contains WHAT???
function SearchFiles() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var sh0 = sheet.getSheets()[0];
var search0 = sh0.getRange("B1").getValue();
//Please enter your search term in the place of Letter
var searchFor = 'title contains "Joshs File"' + 'and fullText contains "X"';
var names =[];
var fileIds=[];
var files = DriveApp.searchFiles(searchFor);
while (files.hasNext()) {
var file = files.next();
var name = file.getName();
names.push(name);
}
for (var i=0;i<names.length;i++){
Logger.log(names[i]);
}
var body = Logger.getLog();
var range=sh0.getRange("A5");
range.setValue(body);
}

Try using implementing this code:
function SearchFiles(){
var textString = "Sample";
var files = DriveApp.getFolderById(FolderID).searchFiles(
'fullText contains "'+textString+'"');
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName());
}
}
Just like how you concatenate a variable and string in JavaScript you have to use "+" in order for it to be recognized as a variable.
Hope this helps.

Related

Reading long sequence of digit as string

I'm using EPPlus to read a customer database.
From time to time in a text cell I'm reading as string, the customer wrote a long sequence of digit
My code read it as exponential format.
Is there a way to force the reading as string?
Here's the code snippet I'm using
using (ExcelPackage xlPackage = new ExcelPackage(new FileInfo(xlsFile))) {
var myWorksheet = xlPackage.Workbook.Worksheets.First();
while (!string.IsNullOrEmpty(myWorksheet.Cells[rowNum, 1].GetValue<string>()))
{
var cell = myWorksheet.Cells[rowNum, 20];
var idDoc = cell.GetValue<string>(),
// do something with idDoc
rowNum += 1;
}
}
when the cell contains, let's say 1790002099190700, idDoc is "1,7900020991907E+15"
What you are seeing make sense as excel will store the value as a double like any other numeric value.
It looks like you are exporting from a database to excel. I would assume that when exported there is no formatting set in Excel in which case using the .Text value of the cell object simply fall back to "General" in excel.
Say you have this:
So, what you end up with is this:
[TestMethod]
public void Cell_Digits_As_String()
{
//https://stackoverflow.com/questions/58058900/reading-long-sequence-of-digit-as-string
var fi = new FileInfo(#"c:\temp\Cell_Digits_As_String.xlsx");
using (var package = new ExcelPackage(fi))
{
var workbook = package.Workbook;
var worksheet = workbook.Worksheets.First();
var valCell = worksheet.Cells[1, 1];
var valText = valCell.Text; //Applies "General" unless otherwise specified
var valValue = valCell.Value; //As a BOXED double
var valString = valCell.GetValue<string>(); //Falls back to ChangeType
Console.WriteLine($"Value as text: {valText} ({valText.GetType()})");
Console.WriteLine($" Same as: {((double)valValue).ToString("0.#####", new CultureInfo("es-US"))}");
Console.WriteLine($"Value as value: {valValue} ({valValue.GetType()})");
Console.WriteLine($" Same as: {valValue.ToString()}");
Console.WriteLine($"Value as string: {valString} ({valString.GetType()})");
Console.WriteLine($" Same as: {Convert.ChangeType(valValue, typeof(double)).ToString()}");
}
}
Which shows this in the out:
Value as text: 1790002099190700 (System.String)
Same as: 1790002099190700
Value as value: 1.7900020991907E+15 (System.Double)
Same as: 1.7900020991907E+15
Value as string: 1.7900020991907E+15 (System.String)
Same as: 1.7900020991907E+15
So, it would seem that using .Text is the most convenient to get what you want. But if you are concerned about the formatting being altered in any way or just want to be absolutely sure, just do:
try
{
((double)valCell.Value).ToString("0.#");
}
catch (Exception ex)
{
//Handle it...
}

Using getBlob() with activesheet to create pdf is missing recent updates [duplicate]

This question already has an answer here:
Creating and Sending sheets in the same function
(1 answer)
Closed 4 years ago.
I'm trying to save a single-sheet spreadsheet to pdf. Many blogs explain how to do this using getBlob() so I ended up with this:
var theBlob = jobSpreadSheet.getBlob().getAs('application/pdf');
var newFile = getPdfFolder().createFile(theBlob.setName(fileName + ".pdf"));
To create jobSpreadSheet I have created a new spreadsheet:
var tempSpreadsheet = SpreadsheetApp.create(name);
var driveTempFile = DriveApp.getFileById(tempSpreadsheet.getId());
var jobsFolder = getJobsFolder();
var driveNewFile = driveTempFile.makeCopy(name, jobsFolder);
var jobSpreadsheet = SpreadsheetApp.open(driveNewFile);
Next I copy a template into the new spreadsheet and remove the empty first sheet:
var jobCard = jobCardTemplate.copyTo(jobSpreadSheet).setName('Job Card');
jobSpreadSheet.deleteSheet(jobSpreadSheet.getSheets()[0]);
Then I update a few cells in the jobCard and finally create the pdf.
All the steps work except creating the pdf. The pdf is created, it contains the template, but not the updated values.
Should I make the create pdf step somehow wait for the updates to be saved?
Are you calling .saveChanges() anywhere in your script? (Before getting the blob.)
Not sure if this is required with sheets, but I had a similar issue in docs because I was not saving changes before getting the blob.
Edit:
Just tested with the following code and it appears that .saveChanges is not required:
function test() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
sheet.getRange(1, 1, 1, 1).setValue("Test");
var file = DriveApp.getFileById(ss.getId());
var blob = file.getBlob().getAs('application/pdf');
DriveApp.createFile(blob);
}

Autofitting column in combination with setting numberformat will autofit using unformatted text as measurement

When I use EPPlus to autofit a column that is formatted as a date string, the autofit mechanism is using the unformatted string as measurement for how wide the column should become.
Is it a bug or did I do something wrong?
Code
sheet.Column(2).Style.Numberformat.Format = "yyyy-MM-dd hh:mm";
sheet.Cells.AutoFitColumns();
Result:
widening the second column in excel
Autofit using no formatting, notice that the second column is having the same width as the supposed-to-autofit column in the first picture.
For completion, here is the result when no autofit is used
It could be your font settings either in your code or globally in excel. Try running this test (I am posting this as an answer since I cannot fit it in a comment):
[TestMethod]
public void Auto_Col_Fomat_Test()
{
//Throw in some data
var datatable = new DataTable("tblData");
datatable.Columns.AddRange(new[]
{
new DataColumn("Col1", typeof (int)), new DataColumn("Col2", typeof (DateTime)), new DataColumn("Col3", typeof (object))
});
for (var i = 0; i < 10; i++)
{
var row = datatable.NewRow();
row[0] = i; row[1] = DateTime.Now.AddDays(i); row[2] = Path.GetRandomFileName();
datatable.Rows.Add(row);
}
//Create a test file
var fi = new FileInfo(#"c:\temp\Auto_Col_Fomat.xlsx");
if (fi.Exists)
fi.Delete();
using (var pck = new ExcelPackage(fi))
{
var workbook = pck.Workbook;
var sheet = workbook.Worksheets.Add("Sheet1");
sheet.Cells.LoadFromDataTable(datatable, true);
sheet.Column(2).Style.Numberformat.Format = "yyyy-MM-dd hh:mm";
sheet.Cells.AutoFitColumns();
pck.Save();
}
}
If this shows the same thing you may have changed your default excel font or zoom which means you may have to set the font in code to Body Font size 11 (at least that was 2013 uses). If it doesnt show post more of your code.
I had the same issue.
Here is my work around:
First call AutoFitColumns, then add some padding to the column that has a special format:
cells[sheet.Dimension.Address].AutoFitColumns();
sheet.Column(2).Width *= 1.25;

Is there a way to get 'named' cells using EPPlus?

I have an Excel file that I am populating programmatically with EPPlus.
I have tried the following:
// provides access to named ranges, does not appear to work with single cells
worksheet.Names["namedCell1"].Value = "abc123";
// provides access to cells by address
worksheet.Cells["namedCell1"].Value = "abc123";
The following does work - so I know I am at least close.
worksheet.Cells["A1"].Value = "abc123";
Actually, its a bit misleading. The Named Ranges are stored at the workBOOK level and not the workSHEET level. So if you do something like this:
[TestMethod]
public void Get_Named_Range_Test()
{
//http://stackoverflow.com/questions/30494913/is-there-a-way-to-get-named-cells-using-epplus
var existingFile = new FileInfo(#"c:\temp\NamedRange.xlsx");
using (var pck = new ExcelPackage(existingFile))
{
var wb = pck.Workbook; //Not workSHEET
var namedCell1 = wb.Names["namedCell1"];
Console.WriteLine("{{\"before\": {0}}}", namedCell1.Value);
namedCell1.Value = "abc123";
Console.WriteLine("{{\"after\": {0}}}", namedCell1.Value);
}
}
You get this in the output (using an excel file with dummy data in it):
{"before": Range1 B2}
{"after": abc123}

Generate a Google Doc (and PDF) of row data when a cell in a row of a sheet is edited

I have a Google Form and Google Sheet set up to collect information I need. I currently have a script that will send me, and the form submitter, an email with a PDF attached that contains the contents of their form submission.
I am trying to edit that script and create another one that sends me a new version of the PDF after I go in and make a change to one of the cells associated with the original form submission (update the status of an issue, add notes, correct grammar, etc.).
This is what I have, I am still very new at programming and would appreciate any help...
(18 NOV #1425) It works! var last_column was not allowing the column after the edited cell to be defined. When I replaced last_column in var data with the actual number of columns that contained the data it worked great! Thank you to everyone who helped me figure this out, and learn a little along the way!
function onSheetEdit(e) {
var source = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = source.getSheetByName("Form Responses 1");
var range = source_sheet.getDataRange();
var ActiveRow = source_sheet.getActiveRange().getRow();
var data = source_sheet.getRange(ActiveRow,1,1,4).getValues();
var columnA = data[0][0];
var columnB = data[0][1];
var columnC = data[0][2];
var columnD = data[0][3];
(18 NOV #0800) Another friend suggested I change the beginning to this... The email also sends, and now I am getting "1" "1" "/" and "1" in my four document placeholders...
function onSheetEdit(e) {
var source_sheet = e.source.getActiveSheet();
if (source_sheet.getName() !== "Form Responses 1") return; //exit the script if edits are done on other sheets
var data = source_sheet.getRange(e.range.rowStart, 1, 1, source_sheet.getLastColumn())//(StartRow,StartColumn,NumberofRowstoGet,NumberofColumnstoGet)
.getValues()[0];
Logger.log(data);
var columnA = data[0][0];
var columnB = data[0][1];
var columnC = data[0][2];
var columnD = data[0][3];
(17 NOV #1845) I had a friend help me from work and this is as far as we got... The email sends now, but the placeholders are not populating the data correctly in the PDF file attachment. It appears that the only data that is populating is data from row 1, and of that data, only the cell that was edited, and the data in the cells to the right of it...
function onSheetEdit(e) {
var source = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = source.getSheetByName("Form Responses 1");
var range = source_sheet.getDataRange();
var last_column = source_sheet.getActiveRange().getColumn();
var ActiveRow = source_sheet.getActiveRange().getRow();
var data = source_sheet.getRange(ActiveRow,1,1,last_column).getValues();
var columnA = data[0][0];
var columnB = data[0][1];
var columnC = data[0][2];
var columnD = data[0][3];
(16 NOV #1700) I edited the script to this but still no emails generated. I get this error emailed to me when script fails: "Cell reference out of range (line 13, file "Copy of Form confirmation emails")". Line 13 is "var row".
function onSheetEdit() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = source.getActiveSheet()
var row = source_sheet.getActiveCell().getRow();
var last_column = source_sheet.getLastColumn();
var data = source_sheet.getRange(row,1,1,last_column).getValues();
var columnA = data[0][0];
var columnB = data[0][1];
var columnC = data[0][2];
var columnD = data[0][3];
(16 NOV # 1330) I tried this instead but still no emails generated...
function onSheetEdit() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = source.getActiveSheet()
var row = source_sheet.getActiveCell().getRow();
var last_column = source_sheet.getLastColumn();
var data = source_sheet.getRange(row,1,1,last_column);
var columnA = data.values[0];
var columnB = data.values[1];
var columnC = data.values[2];
var columnD = data.values[3];
Original script...
function onSheetEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var rows = sheet.getActiveCell().getRow();
var columnA = e.values[0];
var columnB = e.values[1];
var columnC = e.values[2];
var columnD = e.values[3];
var docTemplate = "1WyWeCLQQ3en1EbKjOLcWxlOLc0fHHDpZrB9yfXZ7nv8";
var docName = "Test form script";
var carbonCopyEmail = "jeffery.crane#goarmy.com";
var submitterEmail = columnB;
var dataName = columnC;
var submitDate = columnA;
var attachmentName = docName + ' for data ' + dataName
var submitterEmailPlaceholder = 'keyUsername';
var submitDatePlaceholder = 'keyTimestamp';
var templatePlaceholder1 = 'keyQuestion1';
var templatePlaceholder2 = 'keyQuestion2';
var submitterSubject = "Test Script Confirmation Email for data " + dataName;
var submitterBody = "Attached is a PDF confirmation sheet with the details of your submission of data: " + dataName + " submitted on " + submitDate;
var carbonCopySubject = "Test Script Submission Notification Email for data " + dataName;
var carbonCopyBody = "Attached is a PDF confirmation sheet with the details of " + submitterEmail + "'s submission of data: " + dataName + " on " + submitDate;
//Gets document template defined by the docID above, copys it as a new temp doc, and saves the Doc’s id
var copyId = DocsList.getFileById(docTemplate)
.makeCopy(attachmentName)
.getId();
//Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
//Get the document’s body section
var copyBody = copyDoc.getActiveSection();
//POSSIBLE MODIFICATION TO ADD LINES OF CODE
//Replace place holder keys with the spreadsheet values in the google doc template
//This section of the script looks for instances where the key appears in the Google Doc and replaces the instance
//with the defined variable
//For instance, whenever "keyUserName" (defined above as submitterEmailPlaceholder) appears in the Google Doc,
//the value from the spreadsheet in columnB replaces "keyUserName"
copyBody.replaceText(submitDatePlaceholder, columnA);
copyBody.replaceText(submitterEmailPlaceholder, columnB);
copyBody.replaceText(templatePlaceholder1, columnC);
copyBody.replaceText(templatePlaceholder2, columnD);
//Save and close the temporary document
copyDoc.saveAndClose();
//Convert temporary document to PDF
var pdf = DocsList.getFileById(copyId).getAs("application/pdf");
//Attaches the PDF and sends the email to the form submitter
MailApp.sendEmail(submitterEmail, submitterSubject, submitterBody, {htmlBody: submitterBody, attachments: pdf});
//Attaches the PDF and sends the email to the recipients in copyEmail above
MailApp.sendEmail(carbonCopyEmail, carbonCopySubject, carbonCopyBody, {htmlBody: carbonCopyBody, attachments: pdf});
//Deletes the temporary file
DocsList.getFileById(copyId).setTrashed(true);
}
You cannot do data.values, data is a range object, you should do getValues() to get an array of values: data[row][col]
var data = source_sheet.getRange(row,1,1,last_column).getValues()
var columnA = data[0][0];
var columnB = data[1][0];
var columnC = data[2][0];
var columnD = data[3][0];
Why instead of mess manually with the cells values of the responses sheet you don't use the form edit link? You can put it into the mail you are already sending.
You can get it from:
var editLink = lastResponse.getEditResponseUrl();
When the form is submitted again from the edit link the script you wrote script will be run again sending the updated PDF.