Saving charts as images when converting xls to Google Sheets - Google Script - google-apps-script

I have a standard script from the Internet which converts xls to Google Sheets. The charts in the output file got converted to images which is a good thing, I needed charts to be saved as images as the original xls have specific formatting I would like to preserve but the problem is that they look awful - the color shaded, the font dropped to a very small size, the legend floats somewhere. Ultimately I need to have these images to be saved in Google Slides. So, what I was thinking is to find a way (1) to save images from xls and saves directly in Google slides or (2) to save images from xls to Google Sheets but somehow preserve the original formatting and then, run another code that saves the images to the target Slides. Interestingly, I have not found any mention of people complaining of the loss of the chart formatting.
function convertExceltoGoogleSpreadsheet2(fileName) {
try {
fileName = fileName || "name";
var excelFile = DriveApp.getFilesByName(fileName).next();
var fileId = excelFile.getId();
var folderId = Drive.Files.get(fileId).parents[0].id;
var blob = excelFile.getBlob();
var resource = {
title: excelFile.getName().replace(/.xlsx?/, ""),
key: fileId,
parents: [{id: 'id'}]
};
Drive.Files.insert(resource, blob, {
convert: true
});
} catch (f) {
Logger.log(f.toString());
}
}

Related

How to make Google Slide update value WITHOUT having to manually open it? [duplicate]

This question already has answers here:
pdf is created from google slide, but with the markers populated (via GAS)
(1 answer)
Created PDF does not reflect changes made to the original document
(2 answers)
Converting a google doc to a pdf results in blank pdf, google scripts
(1 answer)
Closed 3 months ago.
I have a Google Sheet with a Google Apps Script that basically intends to do the following when triggered:
Open a specific Google Slides file (it's a template)
Duplicate it into a specific subfolder
Change some placeholder values of this copy
Send this new Google Slide via Email as a PDF.
Everything works great EXCEPT for step 3, which for some reason ONLY updates when I manually open this new file. So the PDF that I receive via email actually still contains the placeholder values, as does the "preview" I see on my Drive before opening the Slides presentation. However, if I open it, it automatically shows the new updated values. I can't figure out why this might be happening.
Things I tried:
Add Utilities.sleep() to allow for the values to update, but it doesn't seem to work. Only opening it does it.
Add a line to .openById() again in case this "forces it to open", but doesn't work.
Adding a loop to refresh each slide.
This is a minimal reproducible code that I have, but would require a Google Slide with two placeholders as "[var_0]" and "[var_1]":
const idTemplate = "1BugZRdW8aOzgPOZun-j_U60lC-yXQFXug3R2-MR7AFs";
function generatePresentationData() {
var s = SpreadsheetApp.getActive();
//Data is in A2:B2 of "Records" sheet.
var ss = s.getSheetByName("Records");
var data = ss.getRange("A2:B2").getValues();
//Get the Google Slides template
var file = DriveApp.getFileById(idTemplate);
//Create a copy of the template into a specific folder, and get the ID of this copy
var newParte = file.makeCopy("New Parte", DriveApp.getFolderById("1rCEYVilGiOlxh03aFANzD4qgKXKBmODh"));
var newParteId = newParte.getId();
//Get the slides of this file.
var slides = getSlides_(newParteId);
//Replace the placeholders with the value in A2:B2. This is the part that doesn't actually "shows up" on this new file until I manually open it from my Drive. It does work correctly, so I don't think the issue lies here
writeDataToPlayersSlide_(slides, data);
//I have tried adding a wait period but didn't work
Utilities.sleep(60000);
//I also tried defining the file again before proceeding to send it via email, but again didn't work
var newParte = DriveApp.getFileById(newParteId);
//I also tried refreshing each slide
refreshSlides(SlidesApp.openById(newParteId));
//Get this new file as a Blob
var theBlob = newParte.getBlob().getAs('application/pdf');
var nameFile = 'Test.pdf';
var email = "mail#gmail.com";
var subject = 'Test Subject';
var body = 'Hi!, <br/>Here is your file.';
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments: [{
fileName: nameFile,
content: theBlob.getBytes(),
mimeType: "application/pdf"
}]
});
}
function getSlides_(newParteId){
let presentation = SlidesApp.openById(newParteId);
let slides = presentation.getSlides();
return slides;
}
function writeDataToPlayersSlide_(slides, data){
let parte = slides[0];
for (let index=0;index<data[0].length;index++){
parte.replaceAllText(`[var_${index}]`,data[0][index]);
}
}
function refreshSlides(presentation){
// loop through all slides and refresh them
numSlides = presentation.getSlides().length;
for (i = 0; i < numSlides; i++) {
presentation.getSlides()[i].refreshSlide();
}
}
Instead of
//I have tried adding a wait period but didn't work
Utilities.sleep(60000);
//I also tried defining the file again before proceeding to send it via email, but again didn't work
var newParte = DriveApp.getFileById(newParteId);
//I also tried refreshing each slide
refreshSlides(SlidesApp.openById(newParteId));
use
newParte.saveAndClose();
newParte = DriveApp.getFileById(newParteId);
Apparently the problem is that you have missed that Google Apps Script applies changes to Docs Editors files after the script ends.
If order to force Google Apps Script applies the changes at some point, i.e before sendding an email, when making changes to
spreadsheets use SpreadsheetApp.flush()
documents use DocumentsApp.Document.saveAndClose()
presentations use SlidesApp.Presentation.saveAndClose()

Prevent Auto-Format DriveApi 3 Google Apps script

Using the Drive API3, I'm looking for a way to make a copy of a CSV file in Google Sheets format, without having to convert the text to numbers, nor the functions and dates as it can be proposed in the Google Sheets menu:
File>Import>(Select your CSV file)> Untick "Convert text to number, dates and formula".
At the moment, I've got something such as :
function convert(){
var file = DriveApp.getFileById('1234');
var resource = { title : "Title", mimeType : MimeType.GOOGLE_SHEETS,parents : [{id: file.getParents().next().getId()}],}
Drive.Files.copy(resource,file.getId())
}
To illustrate my example : I've got a text in my CSV file "2021-25-03", if I run my macro, the new spreadsheet will automaticaly format my text to a Date and that's not my goal.
TFR.
There doesn't seem to be a setting in the API or in Apps Script to prevent the automatic conversion of numbers and dates, but we can build a script to work around this. Two tools are useful:
Apps Script's Utilities.parseCsv() method, which will build a 2D array of the values in the CSV file (as pure text--it does not interpret numbers and dates).
The fact that Google Sheets interprets any value starting with a single quote ' as text. This is true whether the value is entered in the UI or programmatically.
So the overall strategy is:
Copy the file as you are doing (or just create a new blank file, as we will write the values to it).
Parse the CSV values and prepend a ' to each one.
Write these modified values to the sheet.
Something like this:
function convert(){
var file = DriveApp.getFileById(CSV_FILE_ID);
// Create the copy:
var resource = { title : "Title", mimeType : MimeType.GOOGLE_SHEETS,parents : [{id: file.getParents().next().getId()}],}
var sheetsFile = Drive.Files.copy(resource,file.getId())
// Parse the original csv file:
var csv = Utilities.parseCsv(file.getBlob().getDataAsString())
// csv is a 2D array; prepend each value with a single quote:
csv.forEach(function(row){
row.forEach(function(value, i){
row[i] = "'" + value
})
})
// Open the first (and only) sheet in the file and overwrite the values with these modified ones:
var sheet = SpreadsheetApp.openById(sheetsFile.id).getSheets()[0]
sheet.getRange(1,1,csv.length, csv[0].length).setValues(csv)
}

PDF Realtime down load and conversion

Im Looking for a way to use Google Apps Script to Download PDF file and convert file into Google Sheets.
The reason for this is that website only gives data in PDF form and i cant use Import function to get data for real-time updates
It depends on the way you will download your pdf files.
Here is simple example how you can convert PDF file from your Google Drive into Googe Document:
function pdfToDoc() {
var fileBlob = DriveApp.getFilesByName('test.pdf').next().getBlob();
var resource = {
title: fileBlob.getName(),
mimeType: fileBlob.getContentType()
};
var options = {
ocr: true
};
var docFile = Drive.Files.insert(resource, fileBlob, options);
Logger.log(docFile.alternateLink);
}
To make it work you need to enable Drive API:
Based on the answer: https://webapps.stackexchange.com/a/136948
And as far as I can see there is only DOC as output. Probably you can extract data from DOC and put it into Spreadsheet with script. But it depends on how exactly looks your data.

How to update file contents from gdoc to docx

I am trying to create an Apps Script that will auto-convert all gdoc files to docx files (and all gsheet files to xlsx files). Some parts of the puzzle are addressed here: Batch convert Google Docs files to Microsoft Word, however this creates a new file. I need to keep the URL/ID of the original file. I tried using "setContent" on the File API but that doesn't seem to handle blobs. So thats why I resorted to the advanced Drive API. However, I can't seem to get it to work properly. The filename is replaced, the contents are replaced, but the file stays Google Doc, even though I supply a Mime Type. Any ideas?
This is my code:
function convertGoogleDocsToMicrosoftWord() {
var folderId = "MY_FOLDER_ID"; // Note, eventually I would like to get this from the trigger event somehow so I would welcome ideas on this, too
var files = DriveApp.getFolderById(srcfolderId).getFilesByType(MimeType.GOOGLE_DOCS);
while (files.hasNext()) {
var file = files.next();
var contents = UrlFetchApp.fetch(
"https://docs.google.com/document/d/" + file.getId() + "/export?format=docx",
{
"headers": {Authorization: 'Bearer ' + ScriptApp.getOAuthToken()},
"muteHttpExceptions": true
}
).getBlob();
Drive.Files.update({
mimeType: MimeType.MICROSOFT_WORD,
title: file.getName() + '.docx'
}, file.getId(), contents);
}
}
Some further questions:
assuming I can make this to work, can it update while the file is open?
I would like to be able to launch this on trigger events... however standalone scripts can't seem to be able to get a ref to the current folder they are executed in and then recourse. Is this possible?

Exception: Blob object must have non-null data for this operation. (line 19)

Hi I'm trying to attach multiple Google Doc files from a folder to send to an Email. However, the above exception arises.
The code is as follows
function email() {
// Get attachments folder
var attachementFolderId = "xyz";
Logger.log("Attachement Folder ID: " + attachementFolderId)
var getAttachementFolder = DriveApp.getFolderById(attachementFolderId);
// Get all files from the folder
var files = DriveApp.getFolderById(attachementFolderId).getFiles();
//Get All attachments
var attachements = [];
while (files.hasNext()) {
var file = files.next();
attachements.push(file.getAs(MimeType.GOOGLE_DOCS));
}
MailApp.sendEmail({
to: email,
subject: subject,
attachments: attachements
})
}
This code works fine if the file is either a pdf or a Microsoft Word doc but causes an issue for a Google Doc.
Modification points:
When the official document of getAs(contentType)
) is seen, it says as follows.
The MIME type to convert to. For most blobs, 'application/pdf' is the only valid option. For images in BMP, GIF, JPEG, or PNG format, any of 'image/bmp', 'image/gif', 'image/jpeg', or 'image/png' are also valid.
In this case, unfortunately, MimeType.GOOGLE_DOCS cannot be used for this.
When you want to retrieve the blob from Google Document. It is required to convert it to other mimeType.
When you want to convert it to PDF format, please modify file.getAs(MimeType.GOOGLE_DOCS) to file.getBlob().
When you want to convert it to DOCX format, I think that this thread might be useful.
References:
getAs(contentType)
Related question
Convert Google Doc to Docx using Google Script