I need to overwrite with an Excel file a fixed Google spreadsheet that keep both file ID and sheet ID .
Here below the code written in Google Apps Script that works but everytime generate a new id for the sheet.
function overwrite() {
const xlsxFileName = "XXX.xlsx"; // Please set the filename of XLSX file.
const spreadsheetId = "1JnsV5Vpp0xXj1fNyDeKV04PReYGN4v2oBVcQb6bvBUA"; // Please set the Spreadsheet ID. This Spreadsheet is overwritten by EXCEL data.
const xlsx = DriveApp.getFilesByName(xlsxFileName || "XXX.xlsx");
if (!xlsx.hasNext()) throw new Error("No excel file.");
Drive.Files.update({mimeType: MimeType.GOOGLE_SHEETS}, spreadsheetId, xlsx.next().getBlob());
}
My need is to import the information included in a specific Excel sheet into a specific sheet in Google Sheet. My goal is to be able to keep the spreadsheetID and sheetID in order to be able to link a dashboard in Google Data Studio with automatic update.
Basically you want a spreadsheet which sync with excel file and whenever the data update in Excel file, spreadsheet will update without change it's sheet id and use that spreadsheet to create a report on Looker (formerly Google Data Studio).
What exactly logic use
Create two spreadsheets :
[An excel file convert to the google spreadsheet with updation gid everytime when excel file updates ] (use Apps Script)
[Import data from converted file to new or second google spreadsheet] (use Apps Script).
When you import data to new spreadsheet, the sheet id will never change and you can also use it on Looker.
var dstFileId = 'File_id'; // file Id of Existing Spreadsheet
function convertExceltoGoogleSpreadsheet(fileName) {
fileName = fileName || "excelfile.xlsx"; // excel_file_name.xlsx = name of specific Excel file
var excelFile = DriveApp.getFilesByName(fileName).next();
var fileId = excelFile.getId();
var srcFileId = fileId; // file Id of Excel file
Drive.Files.update({}, dstFileId, DriveApp.getFileById(srcFileId))
};
Upper code for 1st spreadsheet (for convert excel file to google spreadsheet)
****** must add Drive API service ******
var sourceSpreadsheetID = "id_of_1st_spreadsheet";
var sourceWorksheetName = "name_of_worksheet_of_1st_spreadsheet";
var targetSpreadsheetID = "id_of_2nd_spreadsheet";
var targetWorksheetName = "name_of_worksheet_of_2nd_spreadsheet";
function importData() {
var thisSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetID);
var thisWorksheet = thisSpreadsheet.getSheetByName(sourceWorksheetName);
var thisData = thisWorksheet.getDataRange();
var toSpreadsheet = SpreadsheetApp.openById(targetSpreadsheetID);
var toWorksheet = toSpreadsheet.getSheetByName(targetWorksheetName);
var toRange = toWorksheet.getRange(1, 1, thisData.getNumRows(),
thisData.getNumColumns())
toRange.setValues(thisData.getValues());
}
this code for second spreadsheet (import data from 1st spreadsheet without change the sheet id)
Now you can use this new spreadsheet for create your report on Looker
Related
I'm trying to automatically update a Google Sheet from a separate XLSX file, since the XLSX file gets regularly updated, but I need to do some data cleaning. I tried doing a query and importrange neither of which can get data from an xlsx file.
It seems like I need to write a script on the Google Sheet to automatically take the data from the xlsx. Where do I add this, and how would I go about getting started? I have access to both files, so permissions shouldn't be an issue.
Suggestion: Temporarily Convert the Excel File to Google Sheets File to Extract Data
Unfortunately, there is no direct way to extract data from Excel files to Google Sheets using Google Apps Script. As a workaround, you need to first convert your excel file to Google Sheets and then extract the data from the converted file to your output Google Sheets file. You may use the following script as a basis for yours:
function importData() {
var xlsxName = "Test 1.xlsx"; //Change source file name accordingly
var convertID = convert(xlsxName).toString();
var xLSX = SpreadsheetApp.openById(convertID).getSheetByName("Input");
var ss = SpreadsheetApp.openById("<output Sheet ID>").getSheetByName("Output"); //Change output sheet ID
var lastColumn = xLSX.getLastColumn();
var lastRow = xLSX.getLastRow();
ss.getRange(1, 1, lastRow, lastColumn).setValues(xLSX.getDataRange().getValues()); //Sets values from converted xlsx data to output sheet
DriveApp.getFileById(convertID).setTrashed(true); //deletes temporary file
}
function convert(excelFileName) {
var files = DriveApp.getFilesByName(excelFileName);
var excelFile = (files.hasNext()) ? files.next() : null;
var blob = excelFile.getBlob();
var config = {
title: "[Converted File] " + excelFile.getName(), //sets the title of the converted file
parents: [{ id: excelFile.getParents().next().getId() }],
mimeType: MimeType.GOOGLE_SHEETS
};
var spreadsheet = Drive.Files.insert(config, blob);
return (spreadsheet.id); //Returns the ID of the converted file
}
This script involves:
Converting the Excel file to a temporary Google Sheets file.
Importing the data from the temporary Google Sheets file to the desired/output Google Sheets file.
Deleting the temporary Google Sheets file.
NOTE:
Expect a longer runtime when applying this script to a bigger excel file.
You may modify the script to be suitable for your current issue.
The script should be added to your desired output Google Sheets.
Do not forget to add the Drive API service to your script.
Sample Test Case:
Input:
Expected Output:
In a google sheet, I managed to filter file name and file type and list all the particular files needed from a google drive folder based on the conditions into a spreadsheet. I am having an issue to convert the excel files into spreadsheet because I'm opening the selected files using "SpreadsheetApp.openById(id)" in another function() to get the data range from the specific files.
Based on the requirement set, I was been asked to convert the excel files into spreadsheet before getting the range data and export those data into another sheet.
Below are the codes that i created to list the file name and file type, so i believe that the file conversion method might need to be implemented here as well because it involves the file filtering process and these are the files need to be converted later on. Please correct me if I am wrong.
function getChildFiles(parentName, parent, sheet) {
var fileIter = parent.searchFiles("title contains 'completed'and title contains 'Verification
Visit Direct Suppliers'and mimeType='application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet'");
var output = [];
var now = new Date();
var date = new Date();
var copy = new Date(date);
while (fileIter.hasNext()) {
var file = fileIter.next();
var fileName = file.getName();
var fileType = file.getMimeType();
var filecreatedate = file.getDateCreated();
var fileUpdate = file.getLastUpdated()
var path = parentName + ' |--> ' + fileName;
var fileID = file.getId();
var Url = 'https://drive.google.com/open?id=' + fileID;
output.push([fileID, fileName, path, Url,filecreatedate,fileUpdate,copy]);
Logger.log(fileType);}
if (output.length) {
var last_row = sheet.getLastRow();
sheet.getRange(last_row + 1, 1, output.length, 7).setValues(output);
SpreadsheetApp.flush();}
var childFolders = parent.getFolders();
while (childFolders.hasNext()) {
var childFolder = childFolders.next();
var childFolderName = childFolder.getName();
getChildFiles( parentName + ' |--> ' + childFolderName, childFolder, sheet);}}
So I'm trying to implement the file conversion method from excel file to spreadsheet, so that i can extract data from the excel file after the file successfully converted to spreadsheet.
Open XML is generating .xlsx files that can be read by Open Office, but not by Excel itself.
With this as my starting point( Export DataTable to Excel with Open Xml SDK in c#) I have added code to create a .xlsx file. Attempting to open with Excel, I'm asked if I want to repair the file. Saying yes gets "The workbook cannot be opened or repaired by Microsoft Excel because it's corrupt." After many hours of trying to jiggle the data from my table to make this work, I finally threw up my hands in despair and made a spreadsheet with a single number in the first cell.
Still corrupt.
Renaming it to .zip and exploring shows intact .xml files. On a whim, I took a legit .xlsx file created by Excel, unzipped it, rezipped without changing contents and renamed back to .xlsx. Excel declared it corrupt. So this is clearly not a content issue, but file a format issue. Giving up on Friday, I sent some of the sample files home and opened them there with Libre Office. There were no issues at all. File content was correct and Calc had no problem. I'm using Excel for Office 365, 32 bit.
// ignore the bits (var list) that get data from the database. I've reduced this to just the output of a single header line
List< ReportFilingHistoryModel> list = DB.Reports.Report.GetReportClientsFullHistoryFiltered<ReportFilingHistoryModel>(search, client, report, signature);
MemoryStream memStream = new MemoryStream();
using (SpreadsheetDocument workbook = SpreadsheetDocument.Create(memStream, SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new Workbook();
workbook.WorkbookPart.Workbook.Sheets = new Sheets();
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
sheetPart.Worksheet = new Worksheet(sheetData);
Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0)
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = "History" };
sheets.Append(sheet);
Row headerRow = new Row();
foreach( var s in "Foo|Bar".Split('|'))
{
var cell = new Cell();
cell.DataType = CellValues.Number;
cell.CellValue = new CellValue("5");
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
}
memStream.Seek(0, SeekOrigin.Begin);
Guid result = DB.Reports.Report.AddClientHistoryList( "test.xlsx", memStream.GetBuffer(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
return Ok(result);
This should just work. I've noticed other stack overflow discussions that direct back to the first link I mentioned above. I seem to be doing it right (and Calc concurs). There have been discussions of shared strings and whatnot, but by using plain numbers I shouldn't be having issues. What am I missing here?
In working on this, I went with the notion that some extraneous junk on the end of a .zip file is harmless. 7-Zip, Windows Explorer and Libre Office all seem to agree (as does some other zip program I used at home whose name escapes me). Excel, however, does not. Using the pointer at memStream.GetBuffer() was fine, but using its length was not. (The preceding Seek() was unnecessary.) Limiting the write of the data to a length equal to the current output position keeps Excel from going off the rails.
I'm just trying to figure out how to append a single row to an xlsx file. For example, append array = [1 2 3 4 5] to the first empty row using columns 1,2,3,4,5. Ideally I'd start with an empty .xlsx file, and repeatedly rerun this program, which appends a new row to the file each time it is ran.
I'm attempting to use exceljs, but any test writes I try to do to a file say corrupted when I attempt to open them.
edited code (still not working):
var Excel = require('exceljs');
var workbook = new Excel.Workbook();
var sheet = workbook.addWorksheet('rssi');
file = 'testfile.xlsx'
var array = [1,2,3,4,5]
sheet.addRow(array)
workbook.xlsx.writeFile(file)
.then(function() {
console.log('Array added and file saved.')
});
Output is zero bytes and cannot be opened by Microsoft Excel. Says, "The file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file."
Basically, you was trying to add the row in method which was called after file write. Try this example:
var workbook = new Excel.Workbook();
file = 'testfile.xlsx'
var array = [1,2,3,4,5]
var sheet = workbook.addWorksheet('rssi');
sheet.addRow(array)
workbook.xlsx.writeFile(file)
.then(function() {
console.log('Array added and then file saved.')
});
But it add only one row at a time
var spread_sheet = require('spread_sheet');
var row = "1,2,Jack,Pirate";
var filePath = '/home/Pranjal/Desktop/test.xlsx';
var sheetName = "Sheet1";
spread_sheet.addRow(row,filePath,sheetName,function(err,result){
console.log(err,result)
})
Add row to spreadsheet:-
I also stuck with the same functionality issue, so I used 'spread_sheet' module.
It worked for me
I'm trying to write a script that passes information from a Google Spreadsheet, compiles it into a CSV file and emails that file.
My problem: The CSV file on my Excel file looks very different that of my Google Spreadsheet (Dead link).
This is what my Excel file looks like, pasted into another Google Spreadsheet.
The code I am using is below:
function myFunction() {
//get active sheet, the last row where data has been entered, define the range and use that range to get the values (called data)
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow=sheet.getLastRow();
var range = sheet.getRange(1,1,lastRow,91);
var data = range.getValues();
//define a string called csv
var csv = "";
//run for loop through the data and join the values together separated by a comma
for (var i = 0; i < data.length; ++i) {
csv += data[i].join(",") + "\r\n";
}
var csvFiles = [{fileName:"example.csv", content:csv}];
MailApp.sendEmail(Session.getUser().getEmail(), "New Journey Information", "", {attachments: csvFiles});
}
You need to ensure that individual cells' data is atomic. For instance, what you see as a time on the sheet contains a Date object when read by your script, then when that's written to a CSV it may be converted to a date & time string with commas, depending on your locale. (Jan 4, 2013 14:34 for example.) To be safe with punctuation that may be interpreted as delimiters by Excel, you should enclose each element with quotes.
No need to modify your code, as this problem has been solved in one of the examples provided in the Docslist Tutorial. So an easy solution is to replace your code.
Change the first bit of the provided saveAsCSV() as follows, and it will operate either with user input or by passing a filename as a parameter.
function saveAsCSV(filename) {
// Prompts the user for the file name, if filename parameter not provided
fileName = filename || Browser.inputBox("Save CSV file as (e.g. myCSVFile):");
...