Uploading file to iManage/Worksite to a particular folder - excel

I have a particular FolderID and I'd like to upload files to this directory. (I have the reference to the iManage.dll and ImanEXTLib).
I'm struggling with filling out certain fields in the dialog/import window from the code level.
Ideally, I would like to skip this stage to make the upload faster. If I'm conveying all the required data then I can't see any point in the dialog besides clicking OK.
This is the code:
I'm locating the folder by using ManDMS.CreateSearchParameters
After getting results:
Dim rslts as IManFolders
Set rslts = IManSession.WorkArea.SearchFolders(<ManStrings>,<SearchParameters>)
If rslts.Empty = True Then
MsgBox "Found shit."
Elseif rslts.Empty = False Then
Dim TgtFdr as ImanFolder
Set impCmd = ImportCmd
Set context = New ContextItems
Set TgtFdr = rslts.ItemByIndex(1)
Now I'm setting the context items but I have the problem with Matter and Subclass. These are obligatory for the upload but the fields remain empty and I don't know how to address them to complete the upload:
context.Add("IManDestinationObject", TgtFdr)
context.Add("IManExt.Import.DocAuthor", UserID)
context.Add("IManExt.Import.DocDescription", file Name)
context.Add("IManExt.Import.FileName", file path)
context.Add("IManExt.Import.DocClass", "some info")
context.Add("IManExt.Import.DocSubclass", "some info")
context.Add("IManExt.Import.DocMatter", "some info")
impCmd.Initialize context
impCmd.Update
If impCmd.Status = IMANEXTLib.CommandStatus.nrActiveCommand Then
impCmd.Execute
Else
Endif
Tried different things - MatterID, MatterDesc, Custom1,2,3,. Is it possible to skip the part with this window and upload the file in a more straightforwrd way? Also, is it possible to to take out the doc number of the newly imported file at the end?
I tried:
UplDoc = (ImanDocument)context.Item("ImportedDocument")

I figured the whole thing out.
Sort of... I went into the object browser and managed to go around the problem and take advantage of the .DuplicateProfileFromDoc method. I simply mirror the profile of the uploaded doc from other already stored on worksite.
The last bit also solved.
It should be:
Set UplDoc = context.Item("ImportedDocument")
Cheers!

Related

VBA Sharepoint Check In File after Upload

Been using this code for a while to upload a file to SharePoint and noticed the other day that when the file is uploaded, it is checked out to myself automatically and have to go into SharePoint and manually check-in so that others can view the file. Any way to modify or add to my code below to auto check-in a file after it uploads? Totally stumped and any help would be greatly appreciated.
Sub SharePointUpload()
Dim WSN
Dim spAdd
Set WSN = CreateObject("WScript.Network")
spAdd = "https://mysharepoint/test"
WSN.mapnetworkdrive "N:", spAdd
ActiveWorkbook.Save
Dim SharepointAddress As String
Dim LocalAddress As String
Dim objNet As Object
Dim FS As Object
' Where you will enter Sharepoint location path
SharepointAddress = "\\mysharepoint\test"
' Where you will enter the local file path
LocalAddress = "C:\data\sample_file.xlsm"
Set objNet = CreateObject("WScript.Network")
Set FS = CreateObject("Scripting.FileSystemObject")
If FS.FileExists(LocalAddress) Then
FS.CopyFile LocalAddress, SharepointAddress
Else: MsgBox "File does not exist!"
End If
Set objNet = Nothing
Set FS = Nothing
WSN.removenetworkdrive "N:"
End Sub
I had the same issue with our SharePoint Document library even with option Require Check Out switched off - some documents (Word, Excel) were uploaded as Checked Out automatically (green arrow mark) whereas others were in fact Checked In from upload. Moreover when I wanted to Check In manually such documents, I got error message about missing mandatory field, although there was no field in the library set as mandatory.
The reason in my case was the field Title. This field is presented in library as default text field and it is also presented in Office files. I noticed that for Office files with empty field Title the document is automatically Checked Out during upload. When uploaded document contained some text in Title property, no Check Out was set. I also tried to use workflow to change the Title and then Check Out file (after creation), but it was not working - initial Check In was required to start the workflow. Manual change of document properties works but that's too tedious...
The first programmatic option to handle this issue could be to fill Title property of uploaded document when empty (i.e. add file name or any other text). Should work well with many languages. Example with Python:
from docx import Document
path = 'D:/myfile.docx'
document = Document(path)
document_property = document.core_properties
if not document_property.title:
document_property.title = 'Everything is Awesome'
document.save(path)
In VBA Title should accessible via Wb.BuiltinDocumentProperties("Title").
Another successful option for me was to find column Title in Columns of Document library and rename it to something else (I used Titlex as new name), then try to upload new document with empty Title - this time there was no automatic Check Out for the uploaded document. Then I could set the Titlex back to Title without returning the issue.

Change built-in Document properties without opening

I am attempting to run the below line of code in a sub. The purpose of the sub overall is to automatically create agendas for recurring meetings, and notify the relevant people.
'Values for example;
MtgDate = CDate("11/06/2020")
Agenda ="Z:\Business Manual\10000 Management\11000 Management\11000 Communications\Operations Meetings\11335 - OPS CCAR Performance Review Agenda 11.06.20.docx" 'NB it's a string
'and the problematic line:
Word.Application.Documents(Agenda).BuiltinDocumentProperties("Publish Date") = MtgDate
Two questions:
1) Can I assign a document property just like that without opening the document? (bear in mind this vba is running from an excel sheet where the data is stored)
2) Will word.application.documents accept the document name as a string, or does it have to be some other sort of object or something? I don't really understand Word VBA.
Attempts so far have only resulted in
runtime error 427 "remote server machine does not exist or is
unavailable"
or something about a bad file name.
Although Publish Date can be found under Insert > Quick Parts > Document Property it isn't actually a document property. It is a "built-in" CustomXML part, a node of CoverPageProperties, and can be addressed in VBA using the CustomXMLParts collection.
The CustomXML part is only added to the document once the mapped content control is inserted.
Below is the code I use.
As already pointed out for document properties the document must be open.
Public Sub WriteCoverPageProp(ByVal strNodeName As String, ByVal strValue As String, _
Optional ByRef docTarget As Document = Nothing)
'* Nodes: Abstract, CompanyAddress, CompanyEmail, CompanyFax, CompanyPhone, PublishDate
'* NOTE: If writing PublishDate set the content control to store just the date (default is date and time).
'* The date is stored in the xml as YYYY-MM-DD so must be written in this format.
'* The content control setting will determine how the date is displayed.
Dim cxpTarget As CustomXMLPart
Dim cxnTarget As CustomXMLNode
Dim strNamespace As String
If docTarget Is Nothing Then Set docTarget = ActiveDocument
strNodeName = "/ns0:CoverPageProperties[1]/ns0:" & strNodeName
strNamespace = "http://schemas.microsoft.com/office/2006/coverPageProps"
Set cxpTarget = docTarget.CustomXMLParts.SelectByNamespace(strNamespace).item(1)
Set cxnTarget = cxpTarget.SelectSingleNode(strNodeName)
cxnTarget.Text = strValue
Set cxnTarget = Nothing
Set cxpTarget = Nothing
End Sub
You cannot modify a document without opening it. In any event, "Publish Date" is not a Built-in Document Property; if it exists, it's a custom one.
Contrary to what you've been told, not all BuiltinDocumentProperties are read-only; some, like wdPropertyAuthor ("Author"), are read-write.
There are three main ways you could modify a Word document or "traditional" property (which are the ones you can access via .BuiltInDocumentProperties and .CustomProperties):
a. via the Object Model (as you are currently trying to do)
b. for a .docx, either unzipping the .docx, modifying the relevant XML part, and re-zipping the .docx.
c. For "traditional" properties, i.e. the things that you can access via .BuiltInDocumentProperties and .CustomDocumentProperties, in theory you can use a Microsoft .dll called dsofile.dll. But it hasn't been supported for a long time, won't work on Mac Word and the Microsoft download won't work on 64-bit Word. You'd also have to distribute and support it.
But in any case, "Publish Date" is not a traditional built-in property. It's probably, but not necessarily, a newer type of property called a "Cover Page Property". Those properties are in fact pretty much as "built-in" as the traditional properties but cannot be accessed via .BuiltInDocumentProperties.
To modify Cover Page properties, you can either use the object model or method (b) to access the Custom XML Part in which their data is stored. Method (c) is no help there.
Not sure where your error 427 is coming from, but I would guess from what you say that you are trying to see if you can modify the property in a single line, using the fullname of the document in an attempt to get Word to open it. No, you can't do that - you have to use GetObject/CreateObject/New to make a reference to an instance of Word (let's call it "wapp"), then (say)
Dim wdoc As Word.Document ' or As Object
Set wdoc = wapp.Documents.Open("the fullname of the document")
Then you can access its properties, e.g. for the read/write Title property you can do
wdoc.BuiltInDocumentProperties("Title") = "your new title"
wdoc.Save
If Publish Date is the Cover Page Property, once you have a reference to the Word Application and have ensured the document is open you can use code along the following lines:
Sub modPublishDate(theDoc As Word.Document, theDate As String)
' You need to format theDate - by default, Word expects an xsd:dateTime,
' e.g. 2020-06-11T00:00:00 if you only care about the date.
Const CPPUri As String = "http://schemas.microsoft.com/office/2006/coverPageProps"
Dim cxn As Office.CustomXMLNode
Dim cxps As Office.CustomXMLParts
Dim nsprefix As String
Set cxps = theDoc.CustomXMLParts.SelectByNamespace(CPPUri)
If cxps.Count > 0 Then
With cxps(1)
nsprefix = .NamespaceManager.LookupPrefix(CPPUri)
Set cxn = .SelectSingleNode(nsprefix & ":CoverPageProperties[1]/" & nsprefix & ":PublishDate[1]") '/PublishDate[1]")
If Not (cxn Is Nothing) Then
cxn.Text = theDate
Set cxn = Nothing
End If
End With
End If
Set cxps = Nothing
As for this, "Will word.application.documents accept the document name as a string", the answer is "yes", but Word has to have opened the document already. as mentioned above. Word can also accept an integer index into the .Documents collection and may accept just the name part of the FullName string.
Finally, if you do end up using a "traditional Custom Document Property", even after you have set the property and saved the document (approximately as above) you may find that the new property value has not actually saved! If so, that's down to an old error in Word where it won't save unless you have actually visited the Custom Document Property Dialog or have modified the document content in some way, e.g. adding a space at the end.

Error in saving minitab graphs and plots: "...collection is empty and contains no valid output object"

I want to automate GageR&R study in minitab.
I found code but the line mtbProject.Commands.Item(1).Outputs.Item(1).Graph.SaveAs.
Gives
Run time error:"IOutput: IOutput collection is empty and contains no valid output object"
Sub msa_macro()
'
' msa_macro Macro
'
'
Dim MtbApp As Mtb.Application
Dim mtbProject As Mtb.Project
Dim mtbWorksheet As Mtb.Worksheet
Set MtbApp = New Mtb.Application
Set mtbProject = MtbApp.ActiveProject
Set mtbWorksheet = mtbProject.ActiveWorksheet
MtbApp.UserInterface.Visible = True
MtbApp.UserInterface.DisplayAlerts = True
mtbProject.ExecuteCommand "Execute 'C:\Amir\DataAnalysis2\MSA_FixtureMill_STC049\MSA_STC049_BSM\Results_Files\readfileMinitab_test.mtb' 1."
mtbProject.Commands.Item(1).Outputs.Item(1).Graph.SaveAs "C:\Result_Files\grph1.png", True, GFJPEG
End Sub
The problem is, that you want to save the Outputs.Item(1) from Commands.Item(1). So you address the first command that you called, which is "Excecute … ", and this has no Output-Item. Therefore the IOutputs Collection for this Command-Item is empty.
The Output-Collection is defined as the Items of Outputs for each command. What you would want to do, is to save the first Output-Item of the command with which you created the graph.
It would be very helpful, if you could provide some information about your readfileMinitab_test.mtb. What are you doing in this .mtb file, is it also a macro-enabled file? I would guess, that you create the graph in this file?
If you want to save your graph as a .png, I guess you might need the MtbGraphFiletype GFPNGColor instead of GFJPEG. You also don´t need to save the file as grph1.png (just grph1 will suffice), as this is done automatically, because you tell Minitab to save it in a specific filetype.
You could also use the digit-code for the Filetypes (which is a little bit shorter). This would mean GFPNGColor = 3 and GFJPEG = 1. For some further information about this I recommend you the Minitab-Automation-Guide.
An example code could look as following:
'This is the first Command Minitab is executing
mtbProject.ExectueCommand "Execute <something>"
'This is the second Command Minitab is executing
mtbProject.ExecuteCommand "Boxplot C" & CStr(i as Integer)
'We want to Save the Graph, which we created with Command 2. We created one graph with
'this Command, to we only have 1 Output.
mtbProject.Commands.Item(2).Outputs.Item(1).Graph.SaveAs <path as String>, True, 3
Thanks Florian. Yes you are right, I figured it out that I am trying to read the output of the wrong command.
I wanted to execute a sequence of 'Gage R&R' commands and to save an output graph. It is completed now.
Thanks again for the helping answer.

Populating template PDF using VBA

I'm trying to fill out template PDF with data from excel worksheet using VBA and here's what I have so far;
FILE_NAME_TEMPLATE = "path_to\template.pdf"
Set gApp = CreateObject("AcroExch.app")
Set avDoc = CreateObject("AcroExch.AVDoc")
If avDoc.Open(FILENAME, "") Then
Set pdDoc = avDoc.GetPDDoc()
Set jso = pdDoc.GetJSObject
'populating pdf fields here, no issues
FILE_NAME_RESULT = "path_to\result.pdf"
pdDoc.Save PDSaveFull, FILE_NAME_RESULT
pdDoc.Close
End If
avDoc.Close (True)
As is, code populates and saves template.pdf, however I'd like to leave template file unchanged and create the new result.pdf with populated data. Please explain what am I doing wrong and thank you for your time.
(Not enough points to just comment yet, so posting as an answer instead)
Is pdDoc.Close a Function and if so, what's its return value?
As a workaround, you could copy the template to the result file first and then work on the file.
FileCopy FILE_NAME_TEMPLATE, FILE_NAME_RESULT
Let me add a coding style best practice recommendation: use all upper-case names for constants only. For actual variables, use mixed case names (like you did with e.g. pdDoc.
I was looking for this too and it took me days: Just use the document flag (long) instead of the argument:
pdDoc.Save 1, FILE_NAME_RESULT

Determine Image in Excel Comment

I have found plenty of vba for inserting images into a comment
Selection.ShapeRange.Fill.UserPicture "C:\Temp\Pictures\ewe.jpg"
How can you determine the image already used for an comment?
I would like to extract the embedded image names if possible.
Is there not a property to access that will give me this?
In the comment Fill Effects dialog box the image name somehow seems to be accessible.
Sorry, I didn't have the reputation to just comment on your question for clarification.
I made a test file, inserted a comment and image in that comment, and then extracted the base files. I then checked them all for the original file name. I also found the embedded JPEG and decoded it to get the metadata. As you've noted, the original file names are stored in xl\drawings\vmlDrawing1.vml (once you've extracted the xml files from the excel file by appending .zip to the filename and then running an unzip utility on it). I did find the file name, but not the path or file type, so I'm fairly certain that the path and file type aren't preserved.
If just the file name is sufficient for you, then that file contains information for each drawing that you have, and those will include the cell location, although they're 0 based, so you'd have to add one to get the actual row and column. My question is two part:
1) Is the file name alone sufficient, or did you need the entire path? If you needed the entire path, I think you're out of luck, since the paths are on a different computer and you can't even search for them if you do extract the file name.
2) If that is all you need, does the solution have to be VBA? In the past, I have programmatically unzipped and manipulated the xml base files, but it's a little tricky. It's simplified by the fact that you only have to read out the data, so that's a plus. I did it in .net before, but I'm sure that if it had to be VBA it could be done, but it would be simpler if you were open to the type of solution.
Let me know, I'd be happy to help you out.
====================================================================================
Try this: make a copy of the spreadsheet, append .zip (test.xlsm.zip), and then extract the files manually. Change vmlPath to the location of your xl\drawings\vmlDrawing1.vml file. Then run this. I did make some assumptions, for instance, I assumed that the order of the nodes and attributes would always be the same and so I used hardcoded indexes (shp.attributes(0), etc) instead of using logic to make sure I had the correct node or attribute, but you seem like you know your way around VBA, so I'm just going to code a barebones. This will need a reference to Microsoft XML 6.0.
Sub vmlParse()
Dim vmlPath As String: vmlPath = "C:\Users\Lenovo\Desktop\test - Copy.xlsm\xl\drawings\vmlDrawing1.vml"
Dim this As Worksheet: Set this = ActiveSheet
Dim doc As New DOMDocument, shps As IXMLDOMNodeList
Dim shp As IXMLDOMNode, n As IXMLDOMNode, a As IXMLDOMAttribute
Dim fileName As String, productID As String
Dim rng As Range, r As Long, c As Long
doc.Load vmlPath
Set shps = doc.getElementsByTagName("x:ClientData")
For Each shp In shps
If shp.Attributes(0).nodeValue = "Note" Then
r = 0: c = 0
For Each a In shp.ParentNode.FirstChild.Attributes
If a.nodeName = "o:title" Then
fileName = a.nodeValue
Exit For
End If
Next
For Each n In shp.childNodes
If n.nodeName = "x:Row" Then r = n.text
If n.nodeName = "x:Column" Then c = n.text
Next
Set rng = this.Cells(r + 1, c + 1)
productID = rng.Value
'now you have the productID, the fileName, and the cell location
End If
Next
End Sub
Let me know how that worked out for you.
If c4 contains your comment:
Set shp = Range("C4").Comment.Shape
if shp.Fill.TextureType = msoTextureUserDefined then
end if

Resources