I`m trying to get output of all the files URLs form the current folder, but I only get URL of the first file from the forlder here:
function listFolderContents() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Hub 2');
var foldername = sheet.getRange('D160').getValue();
var linkoutput = sheet.getRange('W160');
var folders = DriveApp.getFoldersByName(foldername);
var folder = folders.next();
var contents = folder.getFiles();
Logger.log(linkoutput);
var file;
var link;
while(contents.hasNext()) {
file = contents.next();
link = file.getUrl();
linkoutput.setValue(link);
}
};
3 more things:
I`d like to have this script looped through the whole column, so it would check each folder name in column D and output files links in the column W;
the best outcome would be if it could output all the 3 links(as each folder would have only 3 files anyways) in the range of W:Y of the same row with the foder name;
and the last if this script could run automatically without a need to open Scripts tool and running the code every time.
thanks in advance!
For this question:
and the last if this script could run automatically without a need to open Scripts tool and running the code every time. thanks in advance!
You can set a Trigger to run when the spreadsheet is opened. Or you could set time triggers, to run daily for example.
Regarding the code, It looks like your are setting the link url always to the same cell (W60).
Related
So I have the script below which allows me to automatically create google drive hyperlinks of files within the same directory:
function myFunction() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var s=ss.getActiveSheet();
var c=s.getActiveCell();
var fldr=DriveApp.getFolderById(*[insert id]*);
var files=fldr.getFiles();
var names=[],f,str;
while (files.hasNext()) {
f=files.next();
str='=hyperlink("' + f.getUrl() + '")';
str2 = f.getName();
names.push([str2,str]);
}
s.getRange(c.getRow(),c.getColumn(),names.length,2).setValues(names);
}
I am very novice, however, so I can't really figure out how I would get this to search through each of the subfolders as well to get their hyperlinks too. I feel as if this is probably relatively simple, but I am not well versed enough in google scripts to do this (if it was python, I could do this easily). Any help would be greatly appreciated.
I believe your goal as follows.
You want to retrieve all files under the specific folder, and put the values of URL and filename to the Spreadsheet.
The specific folder has the subfolders.
You want to achieve this using Google Apps Script.
Modification points:
In your script, the files are retrieved from just under the specific folder.
In order to retrieve all files under the specific folder including the subfolders, it is required to traverse all subfolders.
When above points are reflected to your script, it becomes as follows. In this modification, Drive service is used.
Modified script:
function myFunction() {
// Method for retrieving the file list from the specific folder including the subfolders.
const getAllFiles = (id, list = []) => {
const fols = DriveApp.getFolderById(id).getFolders();
let temp = [];
while (fols.hasNext()) {
const fol = fols.next();
temp.push(fol.getId());
const files = fol.getFiles();
while (files.hasNext()) {
const file = files.next();
list.push([`=hyperlink("${file.getUrl()}")`, file.getName()]);
}
}
temp.forEach(id => getAllFiles(id, list));
return list;
}
const folderId = "###"; // Please set the folder ID.
const names = getAllFiles(folderId);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var c = s.getActiveCell();
s.getRange(c.getRow(), c.getColumn(), names.length, 2).setValues(names);
}
References:
Drive Service
About the file list from the specific folder including the subfolders, this thread might be useful.
I have a JavaFX application that saves data to a local file data.json which, for example, looks like
data = '[{"name":"Jack","pet":"turtle"},{"name":"John","pet":"black mamba"}]'. Periodically the application adds more entries to this file.
In my html file that I am loading to that application I need to show all this info. I have a script tag that loads that file:
<script type="text/javascript" src="../Data/data.json" id="dataSourceScript"></script>
Then in js code I have var mydata = JSON.parse(data) which allows me to load that JSON into mydata variable as described here.
As I need to update the page content when new entries are added, I have a function I call every couple seconds with setInterval() that does that. In order to get the updated file info, I delete that old <script> tag and add a new one (exactly the same), but this means that data now has the updated info:
var oldScript = document.getElementById("dataSourceScript")
if(oldScript)
oldScript.remove()
var newScript = document.createElement("script")
newScript.setAttribute("id", "dataSourceScript")
newScript.setAttribute("src", "../Data/data.json")
document.body.appendChild(newScript)
var mydata = JSON.parse(data)
//then I just add the new entry to DOM, if there is a new entry
It all works great. If I open my html file in browser and then add a new entry to the file, in a few seconds the page gets updated and shows the new entry too. However, for some reason it does not work in my JavaFX application. It loads the file just once from the initial <script> tag, but if I change data.json file, nothing happens. I have to close the application and reopen it in order to get the new info shown on the page.
(I didn't find any other way to read a file that would work. FileReader just stops reading when a file gets updated, which defeats the purpose; fetch() and XMLHttpRequest() both get blocked by CORS policy; I cannot create a server to request files or install Node or anything else, I need pure html+js to be the UI)
Figured it out thanks to the comments, thanks guys.
Yes, the file I loaded from script tag was being cached and not being updated. A solution is very easy, I just needed to create a variable counter and add it as a version to the new script every time I create it, so it's considered a new one
var version = 0
...
var oldScript = document.getElementById("dataSourceScript")
if(oldScript)
oldScript.remove()
var newScript = document.createElement("script")
newScript.setAttribute("id", "dataSourceScript?version=" + version++)
newScript.setAttribute("src", "../Data/data.json")
document.body.appendChild(newScript)
var mydata = JSON.parse(data)
//then I just add the new entry to DOM, if there is a new entry
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
So I am doing a personal project for my home administration. I would like to automatically when opening my spread sheet (adminSheet.gs) to import .csv files. It is possible to do this manually, but I would like to automate this as I have to import 30+ .csv files, and more coming. I have enabled google apps script (GAS). However GAS is new for me, I am a bit comfortable with Javascript, however it has been a while since I was in college.. I hope you can help me out!
Here are the facts.
I have multiple .csv files, all with a different name. They are located in the same folder called CSVfolder. This folder is within the main folder MAINfolder in Google Drive. They are seperated by the delimiter ; (semicolon). The CSV files have the same data structure and the first row of each .csv file is the same. This first row has been put already in the sheet adminSheet.gs, serving as the header row called HEADER. So the first row needs to be deleted of each .csv file when imported.
I will upload new .csv files in the CSVfolder. These file name follow the following naming structure. ID_01-09-2020_30-09-2020.csv or ID_01-10-2020_31-10-2020.csv. ID followed by a changing date. (the .csv data will be for that period of time. overlapping or duplicated data will not occur, as I will choose the dataset manually). However this would make it of course very neat.
When I open the adminSheet.gs (located in the MAINfolder), it needs to automatically recognise any new .csv file and merge that into the existing adminSheet.gs with all the other (previously imported) .csv data. The new .csv file should merged below the fixed header row HEADER and above the previously imported .csv file. (this can also be explained as: between the HEADER and the data already in the adminSheet.gs) (this can also be explained as: the new data from the .csv should come above the old data already in the adminSheet.gs).
What Google Apps Script could do this?
Here's how the following code works:
gets data from the csv file as an array
inserts a number of rows after the header row
sets the array in the sheet
moves the csv files to an archive folder after importing them so they are not imported again
then moves to the next file until there are no more files to import
You will need to create an archive folder for the csv files to be stored in after they have been imported. I generally make one inside the folder containing the csv folders for this purpose.
In the code, you will need to provide the folder IDs for the archive folder and the root folder (folder that contains your CSV folder) and the name of the destination sheet in your spreadsheet. These can all be set in the first four variable in the code. (I already set csvFolderName to 'CSVfolder' per the information you provided above.
After saving this code, create a trigger on it to run on open.
Here is the code:
function importCSVFiles()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
const csvFolderName = 'CSVfolder'; // Folder containing csv files and the Archive folder
const rootFolderId = 'id_of_folder_containing_CSVfolder'; // Root folder
const archiveFolderId = 'id_of_archiveFolder'; // Archive Folder
const destinationSheetName = 'name_of_destination_sheet_in_spreadsheet'; // destination sheet in spreadsheet
const root = DriveApp.getFolderById(rootFolderId);
const archiveFolder = DriveApp.getFolderById(archiveFolderId);
const fileName =/ *.csv/;
var rootFolders = root.getFolders();
const sheet = ss.getSheetByName(destinationSheetName);
var csvArray = [];
while (rootFolders.hasNext())
{
var folder = rootFolders.next ();
Logger.log('folder.getName()',folder.getName());
if (folder.getName() === csvFolderName)
{
importCSV(folder);
}
else
{
var csvFolder = folder.getFoldersByName(csvFolderName);
while (csvFolder.hasNext())
{
importCSV(csvFolder.next());
}
}
}
function importCSV(folder)
{
var files = folder.getFiles();
while (files.hasNext())
{
var file = files.next();
Logger.log('file.getName()',file.getName());
csvArray = file.getBlob().getDataAsString("UTF-8");
csvArray = Utilities.parseCsv(csvArray);
csvArray.shift();
sheet.insertRowsAfter(1,csvArray.length);
sheet.getRange (2,1,csvArray.length,csvArray[0].length).setValues(csvArray);
file.moveTo(archiveFolder);
}
}
}
If it seems like you are having issues with the delimiter, you may need to set it specifically as a custom delimiter by substituting the above line of code csvArray = Utilities.parseCsv(csvArray); for csvArray = Utilities.parseCsv(csvArray,';');
I have written a script within a gsheet that can create a gdoc based on the information in a row in the spreadsheet.
I am then trying to create a PDF of the gdoc that has been generated by the script in the gsheet. I am trying to make this all one seamless function where the gdoc is created with the pertinent information and then a pdf is automatically created as well. However, the PDF generated is always just a blank page.
I am able to add a script to a gdoc that will function correctly and create a pdf version of itself (or another gdoc), but when I run a function from a gsheet, it is always just the blank one-page pdf, Does anybody know why this is happening, or have a solution?
Here is an example of one of the simpler scripts I've tried and works in the gdoc script - obviously when running it from the gsheet I have to know the ID first and then open the gdoc from that.
function convertPDF(docId)
{
var doc = DocumentApp.getActiveDocument();
var docId = doc.getId();
var docFolder = DriveApp.getFileById(docId).getParents().next().getId();
var docblob = DocumentApp.getActiveDocument().getAs('application/pdf');
docblob.setName(doc.getName() + ".pdf");
var file = DriveApp.createFile(docblob);
var fileId = file.getId();
}
Thanks!
Chris
I am currently writing a Firefox-Addon that automatically prints every new file from my schools website. All the files on the website are in a table and every row (where each file is) has the class "s2d". This is what i have so far:
var self = require("sdk/self");
var uploads;
pageWorker = require("sdk/page-worker").Page({
contentURL: "http://uchronski.de/lernmaterialien/beruflicheschulformen/11fosinformationssystemeundnetzwerktechnik/index.php",
contentScript: ['var uploads = document.getElementsByClassName("s2d");', 'self.port.emit("pageEntriesLenght", uploads.lenght);']
});
pageWorker.port.on("pageEntriesLenght", function(files) {
uploads = files;
});
Here i'm trying to get the current amount of files hosted on the website but "files" is alway null. I have tried it with a pageMod, which worked, but I need to do it with a page worker instead and I have no idea what I did wrong.
You made a spelling mistake in the word 'length' in the contentScript. Try this:
contentScript: ['var uploads = document.getElementsByClassName("s2d");', 'self.port.emit("pageEntriesLenght", uploads.length);']