Search file name starting with A3 and all search through google drive files that have anyone in domain with view access - search

I have this script that searches files starting with 'A3' and then returns date, url, owner in another google sheet.
I want this script to search through all files that are having sharing setting as "anyone in domain with view access".
Currently, the script returns file list in which I am added as viewer/ editor or I am an owner.
function getMyFilesFromDrive() {
var myFiles = DriveApp.searchFiles('title contains "A3"');
var sheet = SpreadsheetApp.getActive().getSheetByName("Files");
sheet.clear();
var rows = [];
rows.push(["ID", "Name", "Url", "email", "Date"]);
while(myFiles.hasNext()) {
var file = myFiles.next();
var ownerEmail = (file.getOwner() != null) ? file.getOwner().getEmail() : "";
if(file != null) {
rows.push([file.getId(), file.getName(), file.getUrl(), ownerEmail, file.getDateCreated()]);
}
}
sheet.getRange(1,1,rows.length,5).setValues(rows);
}

Related

Create Folder and Share with Guest User without Microsoft Account in Sharepoint with CSOM

I am quite new in CSOM/Sharepoint development and have an interesting task to solve. Unfortunately I don't make as much progress with some details as I would like.
A customer of mine wants a secure way to exchange confidential documents. Therefore my idea was to create a folder in Sharepoint for each customer and to share it with the customer as a guest user. So the customer has access to "his" document folder and can upload and download documents there. I can do this manually as well, but I would like to solve this programmatically via CSOM.
The programmatic creation of the folder I have managed so far. Also the file upload is no problem.
However, the release of the folder of the customer is problematic. I managed to share the folder so that the customer can log in with his Microsoft account or that the order is released "for everyone".
What I need is a personal release WITHOUT forcing an MS account. An personal link with verification code etc...
This is my code so far.
public static void CreateAndShareFolder(ClientContext context, string folderName, string userEmail)
{
var listTitle = "Dokumente";
var rootFolder = "Testfolder_ROOT/";
var folder = CreateFolder(context.Web, listTitle, rootFolder + folderName);
var users = new List<UserRoleAssignment>();
users.Add(new UserRoleAssignment()
{
UserId = userEmail,
Role = Role.Edit,
});
var serverRelativeUrl = folder.ServerRelativeUrl;
var absoluteUrl = new Uri(context.Url).GetLeftPart(UriPartial.Authority) + serverRelativeUrl;
/* User gets Email, but with "public" Sharing-Link */
//var userSharingResults = DocumentSharingManager.UpdateDocumentSharingInfo(context, absoluteUrl, users, true, true, true, null, true, true);
/* User gets Email, but needs an MS-Account to View */
var userSharingResults = DocumentSharingManager.UpdateDocumentSharingInfo(context, absoluteUrl, users, false, false, true, null, false, true);
context.ExecuteQuery();
}
// From Stackoverflow: https://stackoverflow.com/a/22010815/3062062
public static Folder CreateFolder(Web web, string listTitle, string fullFolderUrl)
{
if (string.IsNullOrEmpty(fullFolderUrl))
throw new ArgumentNullException("fullFolderUrl");
var list = web.Lists.GetByTitle(listTitle);
return CreateFolderInternal(web, list.RootFolder, fullFolderUrl);
}
private static Folder CreateFolderInternal(Web web, Folder parentFolder, string fullFolderUrl)
{
var folderUrls = fullFolderUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string folderUrl = folderUrls[0];
var curFolder = parentFolder.Folders.Add(folderUrl);
web.Context.Load(curFolder);
web.Context.ExecuteQuery();
if (folderUrls.Length > 1)
{
var subFolderUrl = string.Join("/", folderUrls, 1, folderUrls.Length - 1);
return CreateFolderInternal(web, curFolder, subFolderUrl);
}
return curFolder;
}

Updating a google spreadsheet table with an excel file

I need to update a table that is shared. The info for this table is first collected into an Excel table files and then uploaded to google drive every day. I found some code that converts the .xls files to a google spreadsheet file, I need to copy the data from this converted file and update the shared one each day. My problem now is that the file I will use for updating the shared spreadsheet will be different eachday, so how can I have the script to get the new file ID eachday. I need these updates to be done automatically each day.
This is the code I have found so far but can't seem to get it to work. First part converts the .xls file to google spreadsheet file that part works but i cant seem to get the function for updating the shared table to work, i cant get the ID of the created file. Would also be nice if a function an be added to the code to to delete the files after they have been converted and the shared table has been updated with them.
function importXLS(){
var files = DriveApp.searchFiles('title contains ".xls"');
var destinationFolderId = "ID of folder with .xls file that is being converted each day";
var existingFileNames = getFilesInFolder(destinationFolderId);
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
try {
if (existingFileNames[name] && (name.indexOf('.xls')>-1)) {
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = { title : name,
key : ID,
'parents':[{"id": destinationFolderId}]
}
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
}
} catch (error) {
console.error("Error with file " + name + ": " + error);
}
}
}
/**
* Get an object of all file names in the specified folder.
* #param {string} folderId
* #returns {Object} files - {filename: true}
*/
function getFilesInFolder(folderId) {
var folder = DriveApp.getFolderById(folderId);
var filesIterator = folder.getFiles();
var files = {};
while (filesIterator.hasNext()) {
var file = filesIterator.next();
files[file.getName()] = true;
}
return files;
}
function CopyContent() {
var ID = importXLS(ID);
var source = SpreadsheetApp.openById(importXLS(ID));//the source needs to be the new file i get eachday
var sheet = source.getSheets()[0];
var destination = SpreadsheetApp.openById("ID of shared table here");
sheet.copyTo(destination);
}
Use Paste Special > Paste values only
The copypastetype to use is PASTE_VALUES
Example from https://developers.google.com/apps-script/reference/spreadsheet/range#copytodestination-copypastetype-transposed
// The code below copies only the values of the first 5 columns over to the 6th column.
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange("A:E").copyTo(sheet.getRange("F1"), spreadsheetApp.CopyPasteType.PASTE_VALUES);

Can I delete a file in Acumatica via the API?

I'm creating a file in Acumatica by calling an action from the API, so that I can retrieve the file in my application.
Is it possible to delete the file via API after I'm done with it? I'd rather not have it cluttering up my Acumatica database.
Failing this, is there a recommended cleanup approach for these files?
Found examples of how to delete a file from within Acumatica, as well as how to save a new version of an existing file! The below implementation saves a new version but has the deletion method commented out. Because I built this into my report generation process, I'm not later deleting the report via API, but it would be easy to translate a deletion into an action callable by the API.
private IEnumerable ExportReport(PXAdapter adapter, string reportID, Dictionary<String, String> parameters)
{
//Press save if the SO is not completed
if (Base.Document.Current.Completed == false)
{
Base.Save.Press();
}
PX.SM.FileInfo file = null;
using (Report report = PXReportTools.LoadReport(reportID, null))
{
if (report == null)
{
throw new Exception("Unable to access Acumatica report writer for specified report : " + reportID);
}
PXReportTools.InitReportParameters(report, parameters, PXSettingProvider.Instance.Default);
ReportNode reportNode = ReportProcessor.ProcessReport(report);
IRenderFilter renderFilter = ReportProcessor.GetRenderer(ReportProcessor.FilterPdf);
//Generate the PDF
byte[] data = PX.Reports.Mail.Message.GenerateReport(reportNode, ReportProcessor.FilterPdf).First();
file = new PX.SM.FileInfo(reportNode.ExportFileName + ".pdf", null, data);
//Save the PDF to the SO
UploadFileMaintenance graph = new UploadFileMaintenance();
//Check to see if a file with this name already exists
Guid[] files = PXNoteAttribute.GetFileNotes(Base.Document.Cache, Base.Document.Current);
foreach (Guid fileID in files)
{
FileInfo existingFile = graph.GetFileWithNoData(fileID);
if (existingFile.Name == reportNode.ExportFileName + ".pdf")
{
//If we later decide we want to delete previous versions instead of saving them, this can be changed to
//UploadFileMaintenance.DeleteFile(existingFile.UID);
//But in the meantime, for history purposes, set the UID of the new file to that of the existing file so we can save it as a new version.
file.UID = existingFile.UID;
}
}
//Save the file with the setting to create a new version if one already exists based on the UID
graph.SaveFile(file, FileExistsAction.CreateVersion);
//Save the note attribute so we can find it again.
PXNoteAttribute.AttachFile(Base.Document.Cache, Base.Document.Current, file);
}
//Return the info on the file
return adapter.Get();
}
The response from Acumatica:
S-b (Screen-base) API allows clean way of downloading report generated as file. C-b (Contract-base) simply does not have this feature added. I suggest you provided feedback here: feedback.acumatica.com (EDIT: Done! https://feedback.acumatica.com/ideas/ACU-I-1852)
I think couple of workaround are:
1) use s-b using login from c-b to generate report and get as file (see example below), or
2) create another method to delete the file once required report file is downloaded. For that, you will need to pass back FileID or something to identify for deletion.
example of #1
using (DefaultSoapClient sc = new DefaultSoapClient("DefaultSoap1"))
{
string sharedCookie;
using (new OperationContextScope(sc.InnerChannel))
{
sc.Login("admin", "123", "Company", null, null);
var responseMessageProperty = (HttpResponseMessageProperty)
OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];
sharedCookie = responseMessageProperty.Headers.Get("Set-Cookie");
}
try
{
Screen scr = new Screen(); // add reference to report e.g. http://localhost/Demo2018R2/Soap/SO641010.asmx
scr.CookieContainer = new System.Net.CookieContainer();
scr.CookieContainer.SetCookies(new Uri(scr.Url), sharedCookie);
var schema = scr.GetSchema();
var commands = new Command[]
{
new Value { LinkedCommand = schema.Parameters.OrderType, Value = "SO" },
new Value { LinkedCommand = schema.Parameters.OrderNumber, Value = "SO004425" },
schema.ReportResults.PdfContent
};
var data = scr.Submit(commands);
if(data != null && data.Length > 0)
{
System.IO.File.WriteAllBytes(#"c:\Temp\SalesOrder.pdf",
Convert.FromBase64String(data[0].ReportResults.PdfContent.Value));
}
}
finally
{
sc.Logout();
}
}
Hope this helps. Also, it would be great if you update the stackover post based on these suggestions.
Thanks
Nayan Mansinha
Lead - Developer Support | Acumatica

Display of "is not a valid internal id" in Netsuite Suitescript 1.0 when creating a Search on a particular record

I have created a search in Netsuite using Suitescript 1.0 for searching a particular "Account" using its account number. When I save the following script file, an error is being displayed in "filters[0]" line in the code below, where it says "acctnumber is not a valid internal id.". I am new to Netsuite and would want to know why the error is being displayed, and the solution for the same. Below is the following piece of code written in which the error is being occured.
function COGSAcnt() {
var cOGSAcntNumber = '50001';
var acntNo;
var filters = new Array();
filters[0] = new nlobjSearchFilter('acctnumber', null, 'startswith', cOGSAcntNumber);
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
var acntSearch = nlapiSearchRecord('account', null, filters, columns);
if (acntSearch != null) {
for (x=0; x<acntSearch.length; x++) {
acntNo = ITMSearch[x].getValue('internalid');
}
}
nlapiLogExecution('debug', 'acntNo', acntNo);
return acntNo;
}
NOTE: I want the filter to be acctnumber (Account Number), and using that would want to retrieve the internalid of the account in Netsuite.
This is where NS can be a little confusing. If you look at the NS Record browser (http://www.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2016_2/script/record/account.html) look under the Filters section. Account Number (acctnumber) isn't there. However Number (number) is the filter.
Try rewriting the code to use number instead
function COGSAcnt() {
var cOGSAcntNumber = '50001';
var acntNo = [];
var filters = new nlobjSearchFilter('number', null, 'startswith', cOGSAcntNumber);
var acntSearch = nlapiSearchRecord('account', null, filters, columns);
if (acntSearch != null) {
for (x=0; x<acntSearch.length; x++) {
acntNo.push(ITMSearch[x].getId();
}
}
return acntNo;
}

Querying the number of folders on my Google Drive

I currently loop through the list of google drive folders and return them all with no issues using the following...
FilesResource.ListRequest listRequest = drive.Files.List();
listRequest.Q = "mimeType='application/vnd.google-apps.folder'";
listRequest.PageSize = 1000;
listRequest.Fields = "nextPageToken, files(mimeType, id, name, parents)";
FileList listResults = null;
do
{
if (taskInfo.Cancel.IsCancellationRequested) return;
listResults = listRequest.Execute();
IList<Google.Apis.Drive.v3.Data.File> gObjects = listResults.Files;
if (gObjects != null && gObjects.Count > 0)
{
Debug.WriteLine("Got folder batch of " + gObjects.Count + " folders.");
}
} while (listRequest.PageToken != null);
The only issue I have is I would really like to know if there was a query of some type I could use to ONLY return the COUNT of folders on my Google Drive BEFORE I start listing them in a batch. Is there one?
Try to use Google Drive API Search functionality. So if you're looking for folders you can try:
mimeType = 'application/vnd.google-apps.folder' then perform a count.

Resources