Trying to delete sharpoint file with a "#" in the name - sharepoint

A lot of the documents I’m dealing with at the moment have a “#” in the file name and when listing the files in the folder I got around this issues by doing a simple replace of the encoded value of %25
var fileRefOriginal = file.ServerRelativeUrl;
var fileRef = fileRefOriginal.Replace("#", "%23");
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(sourceContext, fileRef);
using (var fileStream = System.IO.File.Create(fileName))
{
fileInfo.Stream.CopyTo(fileStream);
}
But for some of the files I need to delete and I was just using this after the download;
sourceContext.Web.GetFileByServerRelativeUrl(fileRef).DeleteObject();
sourceContext.ExecuteQuery();
but it wasn’t removing anything and didn’t give an error so I tried this which just says file not found;
var f = sourceContext.Web.GetFileByServerRelativeUrl(fileRef);
sourceContext.Load(f);
f.DeleteObject();
sourceContext.ExecuteQuery();
I’ve tried it with the original name and the converted name (using %25) but seem to be getting no where.

Got this to work, by capturing the files unique ID, then instead of using ;
var f = sourceContext.Web.GetFileByServerRelativeUrl(fileRef);
I used this;
var f = sourceContext.Web.GetFileById(fileId);
Hope it helps someone with the same issue.

Related

Combining multiple xlsx files into a single google sheet for datastudio

I have a folder that will receive multiple xlsx files that will be uploaded via Google forms. There were will be new sheets added a couple of times a week and this data will need to be added.
I want convert all of these xlsx files into a single sheet that will feed a datastudio.
I had started working with this script:
function myFunction() {
//folder ID
var folder = DriveApp.getFolderById("folder ID");
var filesIterator = folder.getFiles();
var file;
var filetype;
var ssID;
var combinedData = [];
var data;
while(filesIterator.hasNext()){
file = filesIterator.next();
filetype = file.getMimeType();
if (filetype === "application/vnd.google-apps.spreadsheet"){
ssID = file.getId();
data = getDataFromSpreadsheet(ssID)
combinedData = combinedData.concat(data);
}//if ends here
}//while ends here
Logger.log(combinedData.length);
}
function getDataFromSpreadsheet(ssID) {
var ss = SpreadsheetApp.openById(ssID);
var ws = ss.getSheets()[0];
var data = ws.getRange("A:W" + ws.getLastRow()).getValues();
return data;
}
Unfortunately that array is returning 0! I think this maybe due to the xlsx issue.
1. Fetch the excel data
Unfortunately, Apps Script can not deal directly with excel values. You need to first convert those files into Google Sheets to access the data. This is fairly easy to do, and can be accomplished using the Drive API (you can check the documentation here) with the following two lines at the top of your code.
var filesToConvert = DriveApp.getFolderById(folderId).getFilesByType(MimeType.MICROSOFT_EXCEL);
while (filesToConvert.hasNext()){ Drive.Files.copy({mimeType: MimeType.GOOGLE_SHEETS, parents: [{id: folderId}]}, filesToConvert.next().getId());}
Please note that this duplicates the existing file by creating a Google Sheets copy of the excel but does not remove the excel file itself. Also note that you will need to activate the Drive API service.
2. Remove duplicates from combinedData
This is not as straightforward as removing duplicate from a regular array, as combinedData is an array of arrays. Nevertheless, it can be accomplished by creating an intermediate object that stores an stringified version of the row array as the key and the row array itself as the value:
var intermidiateStep = {};
combinedData.forEach(row => {intermidiateStep[row.join(":")] = row;})
var finalData = Object.keys(intermidiateStep).map(row=>intermidiateStep[row]);
Extra
I also found another mistake in your code. You should add a 1 (or whichever the first row that you want to read is) when declaring the range of the values to be read, so
var data = ws.getRange("A1:W"+ws.getLastRow()).getValues();
instead of:
var data = ws.getRange("A:W" + ws.getLastRow()).getValues();
As it currently is, Apps Script fails to understand the exact range you want to be read and just assumes that it is the whole page.

Google Apps Script creates sheets version of excel file. Issue with multiple creation of versions.

I found a solution for my original question in another post Google Apps Script creates sheets version of excel file.
Testing with the code provided in the answer I ran into another issue. Every time I run the script it creates the Spreadsheets version of the .xlsx files again even if they already exist. I have tried modifying the code withing the last If with no results. Then went back to run your code as posted in case I have missed something but it keeps creating versions of the same files.
Any idea of what could I do to fix this will be really appreciated.
The code provided int he answer is the following.
// Convert the user's stored excel files to google spreadsheets based on the specified directories.
// There are quota limits on the maximum conversions per day: consumer #gmail = 250.
function convertExcelToGoogleSheets()
{
var user = Session.getActiveUser(); // Used for ownership testing.
var origin = DriveApp.getFolderById("origin folder id");
var dest = DriveApp.getFolderById("destination folder id");
// Index the filenames of owned Google Sheets files as object keys (which are hashed).
// This avoids needing to search and do multiple string comparisons.
// It takes around 100-200 ms per iteration to advance the iterator, check if the file
// should be cached, and insert the key-value pair. Depending on the magnitude of
// the task, this may need to be done separately, and loaded from a storage device instead.
// Note that there are quota limits on queries per second - 1000 per 100 sec:
// If the sequence is too large and the loop too fast, Utilities.sleep() usage will be needed.
var gsi = dest.getFilesByType(MimeType.GOOGLE_SHEETS), gsNames = {};
while (gsi.hasNext())
{
var file = gsi.next();
if(file.getOwner().getEmail() == user.getEmail())
gsNames[file.getName()] = true;
}
// Find and convert any unconverted .xls, .xlsx files in the given directories.
var exceltypes = [MimeType.MICROSOFT_EXCEL, MimeType.MICROSOFT_EXCEL_LEGACY];
for(var mt = 0; mt < exceltypes.length; ++mt)
{
var efi = origin.getFilesByType(exceltypes[mt]);
while (efi.hasNext())
{
var file = efi.next();
// Perform conversions only for owned files that don't have owned gs equivalents.
// If an excel file does not have gs file with the same name, gsNames[ ... ] will be undefined, and !undefined -> true
// If an excel file does have a gs file with the same name, gsNames[ ... ] will be true, and !true -> false
if(file.getOwner().getEmail() == user.getEmail() && !gsNames[file.getName()])
{
Drive.Files.insert(
{title: file.getName(), parents: [{"id": dest.getId()}]},
file.getBlob(),
{convert: true}
);
// Do not convert any more spreadsheets with this same name.
gsNames[file.getName()] = true;
}
}
}
}
You want to convert Excel files in origin folder to Google Spreadsheet and put the converted Spreadsheet to dest folder.
When the filename of converted file is existing in dest folder, you don't want to convert it.
If my understanding is correct, how about this modification?
From:
if(file.getOwner().getEmail() == user.getEmail() && !gsNames[file.getName()])
To:
if(file.getOwner().getEmail() == user.getEmail() && !gsNames[file.getName().split(".")[0]])
Note:
In this modification, when the filename of converted file is found in the dest folder, the file is not converted.
When the filename has the extension like ###.xlsx and it is converted to Google Spreadsheet, it seems that the extension is automatically removed. I think that this is the reason that the duplicated files are created. So I used split(".")[0] for this situation.
Reference:
split()

NotesException: Unknown or unsupported object type in Vector

I'm trying to add new names to the address book programmatically but I'm getting the following error:
[TypeError] Exception occurred calling method NotesDocument.replaceItemValue(string, Array)
Unknown or unsupported object type in Vector
Code snippet below:
var addressBook = session.getDatabase("","names.nsf");
var gView:NotesView = addressBook.getView("($VIMGroups)");
var gDoc:NotesDocument = gView.getDocumentByKey("groupName", true);
var newg:java.util.Vector = [];
var mems:java.util.Vector = new Array(gDoc.getItemValue('Members'));
newg.push(mems);
var newNames:java.util.Vector = new Array(getComponent("NewMems").getValue());
newg.push(newNames);
gDoc.replaceItemValue("Members", newg);
gDoc.save();
Adding a single user works fine, but then it does not save users in the required canonical format below:
CN=John Doe/O=Org
Instead it is saved in the original format below:
John Doe/Org
I look forward to your suggestions. Thanks.
You can't store an Array in a field. Make newg a java.util.Vector instead and integrate with that.
For OpenNTF Domino API the team wrote a lot of code to auto-convert to Vectors, which may cover Arrays.
Don't use an Array (which is a JS thing). Initialize it as a Vector.
var newg:java.util.Vector = new java.util.Vectory();
Then look up the Vector methods to see how to add to that vector. Not sure if you will have to convert the names using the Name method but I would store them as "CN=Joe Smith/O=Test Org" to be sure you got the right format.
I was able to solve the issue using a forloop to loop through the list and push it into a newly created array. Using the forloop seems to make the difference.
var newg = [];
var group = new Array(getComponent("NewMems").getValue()), lenGA = group.length;
for(i = 0; i < lenGA; i++){
newg.push(group[i]);
}
gDoc.replaceItemValue("Members", newg);
gDoc.save();
An explanation about this behaviour will be appreciated.

XSD.exe changes parameters

I'm currently working with the XSD.exe tool to get classes of XSD files.
But when I pass a file to the tool, it changes the path/file.
string fileName = "C:\\TEST\\testFILE.xsd";
Process p = new Process();
p.StartInfo = new ProcessStartInfo("C:\\xsd.exe", "/c /language:CS " + fileName);
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.Start();
StringBuilder error = new StringBuilder();
while (!p.HasExited)
error.Append(p.StandardError.ReadToEnd());
MessageBox.Show(error.ToString());
Thats some example code to show you the problem.
The output looks like:
Error: Could not find file "c:\test\testfile.xsd
Of course there is no such file or directory.
Do you guys have any idea how to solve this?
Thank ;)
I found the problem. The path in the above given example is a bad choice. In fact, the path I'm really using contains spaces. The XSD.exe uses spaces to seperate arguments. So you have to add some extra quotations at the beginning and at the end of the path string.
For example :
string cmdPath= String.Format(#"""{0}""", path);

Get FileDownloadUrl from attachment (Agile PLM)

I've been following the code samples included in Oracle document E15930_01 (Agile PLM Core Web Services User Manual). The samples are in Java, but I've translated what I need to .NET for the project I'm working on.
I can search for an object and return its attachments. I can get all the attachment properties except the one I need, fileDownloadUrl. This field is always blank.
Sample code follows. I thought by setting the property of allFiles to false and downloadUrl to true, I should get a download URL, but I don't. This code returns all the properties for the attachment except the one I want. Any thoughts on what I'm doing wrong?
AttachmentService svc = new AttachmentService();
svc.Credentials = credentials;
AgileGetFileAttachmentRequest[] req2 = InitializeArray<AgileGetFileAttachmentRequest>(1);
AgileFileAttachmentRequestType[] attachments = InitializeArray<AgileFileAttachmentRequestType>(1);
req2[0].classIdentifier = "MyIdentifier";
req2[0].objectNumber = "1234567890";
req2[0].allFiles = false;
req2[0].downloadUrl = true;
req2[0].attachments = attachments;
attachments[0] = new AgileFileAttachmentRequestType();
int rowId = getRowId(tt);
attachments[0].rowId = rowId;
GetFileAttachmentRequestType get = new GetFileAttachmentRequestType();
get.requests = req2;
GetFileAttachmentResponseType resp2 = svc.getFileAttachment(get);
AgileFileAttachmentResponseType[] attchResp = InitializeArray<AgileFileAttachmentResponseType>(1);
attchResp = resp2.responses[0].attachment;
Posting this in case someone else needs to do this or I need to do it later.
I found the data I needed. The download URLs are generated based on XML values in several fields in the database. They're the folder name, filename and FolderVersion on the row you're looking at. You need to parse the XML and retrieve the values to generate the link.
You can get the pattern for the download link through the Get Shortcut button.

Resources