How to refer to a relative path in SolidWorks VBA - vba

I am writing a macro in SolidWorks VBA that is supposed to open all the parts of an assembly and update their design tables. When the assembly and parts are copied to a new location, I want the macro to open the new (copied) parts in their new location. How do I refer to a relative path for the parts instead of an absolute path.
Or: How do I program VBA to change the file location of the parts to the current folder?
I've found some info on how this works in Excel VBA, yet I can't seem to translate this to SolidWorks VBA.
Dim folderpath As String
folderpath = Application.Activeworkbook.Path
I can't figure out with what I should replace "ActiveWorkbook" to get the location of the current assembly. Searching the object browser in SW VBA doesn't show anything usefull either.

You'll want to use swModel.GetPathName. Here's an example.

Related

VBA for Word - UNC Paths

I have a Word document that uses VBA forms to generate the document content based on selection boxes. The VBA copies and pastes from other word documents into the main document. I use explicit paths to specify where it should go find the word documents.
It would be nice to use UNC paths instead, to remove some of the "explicitness" of the file locations (c:\Files\Example\Content\PROFILE.docx) and maybe replace it with something like "..\Content\Profile.docx "
Example of the code:
Sub GenerateProfile()
Dim currentPathProfile As String
currentPathProfileText = ActiveDocument.Path
currentPathProfileText = currentPathProfileText & "c:\Files\Example\Content\PROFILE.docx"
Documents.Open FileName:=currentPathProfileText
Dim currentPathProfileDoc As Document
Set currentPathProfileDoc = Documents(1)
currentPathProfileDoc.Activate
Call CopyWholeContent
currentPathProfileDoc.Close
Call PasteWholeContent
End Sub
If the other word documents are in a relative path position to the template holding the code you can do it. It is easier if they are in a subfolder. Generate the path of ThisDocument (your code holder) and use that as a base.
ThisDocument.Path
However, rather than pull from documents, why not have the text stored in your template in the form of AutoText and use that instead? If the information is needed in more than one template, it can be stored in a global template as AutoText. This is much more flexible and less prone to problems, IMO.

Powerpoint VBA Presentations File names

Consider VBA for PowerPoint -
Is this a valid Presentations function call?
Presentations(".\directory\ppname.ppt")
Note that this will be called from within a PowerPoint presentation VBA, to open another one in a sub-directory.
The Microsoft Presentations examples (and most others) are not specific about the filename forms accepted, e.g. those using the ".", "..", "\" directives recognized in DOS scripts.
This seems to work with Powerpoint 2007.
As described in the comment, it takes a block of text (the TextRange), the starting position and length of file reference, also a LinkAddr. LinkAddr is essentially a DOS-style file reference, like "..\folder\ppfile.ppt".
The intention here is to launch another PowerPoint tool by invoking its show.ppt or show.ppsm file name. The file name can refer to some other directory using MSDOS file name stuff. I don't know whether it can span different machine platforms, but it seems to work within one Windows 10 system.
My difficulty in getting this to work was some full-path links to images, e.g. something like C:\blah\blah\image.jpg, in the Visual Basic code. PowerPoint didn't like these, instead asked about enabling macros, and just hung up when one of my file links were to be executed. By getting rid of the "macro" complaints, this suddenly started working.
Or maybe some bugs have been fixed in recent repairs to my 2007 PowerPoint tools??
Go figure...
Sub InsertLink(ByRef Trange As TextRange, fpos As Long, msglen As Long, LinkAddr As String)
' Insert an HTML link into the selected TextFrame.
' get the character range
Dim Hrange As TextRange
Set Hrange = Trange.Characters(Start:=fpos, length:=msglen)
' make it an HTML link
With Hrange.ActionSettings(ppMouseClick)
.Action = ppActionHyperlink
.Hyperlink.Address = LinkAddr
End With
End Sub

Adding a macro file to an XLSX/XLSM file using Packaging

I'm using System.IO.Packaging to build simple Excel files. One of our customers would like to have an autorun macro that updates data and recalcs the sheet.
Pulling apart existing sheets I can see that all you need to do is add the vbaProject.bin file and change a few types in the _rels. So I made the macro in one file, extracted the vbaProject.bin, copied it into another file, and presto, there's the macro.
I know how to add package parts when they are in XML format, like the sheets or the workbook itself, but I've never added a binary file and I can't figure it out. Has anyone done this before?
Ok I got it. Following TnTinMn's suggestion:
Open a new workbook and type in your macro. Change the extension to
zip, open it, open the xl folder and copy out the vbaProject.bin
to somewhere easy to find.
In your .Net code, make a new Part and add it to the Package as
'xl/vbaProject.bin'. Copy over byte-for-byte from the
vbaProject.bin you extracted above. It will be compressed as you
add the bytes.
Then you have to add a relationship to the workbook that points to
your new file. You can find those relationships in
xl/_rels/workbook.xml.rels.
You also have to add a content type entry at the root of the
document, which goes into the [Content Types].xls. This happens automatically when you use the ContentType parameter of CreatePart
And finally, change the extension to .xlsm or .xltm
I'm extracting the following from many places in my code, so this is pseudo...
'the package...
Dim xlPackage As Package = Package.Open(WBStream, FileMode.Create)
'start with the workbook, we need the object before we physically insert it
Dim xlPartUri As URI = PackUriHelper.CreatePartUri(New Uri(GetAbsoluteTargetUri("/", "xl/workbook.xml"), UriKind.Relative)) 'the URI is relative to the outermost part of the package, /
Dim xlPart As PackagePart = xlPackage.CreatePart(xlPartUri, "application/vnd.ms-excel.sheet.macroEnabled.main+xml", CompressionOption.Normal)
'add an entry in the root _rels folder pointing to the workbook
xlPackage.CreateRelationship(xlPartUri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", "xlWorkbook") 'it turns out the ID can be anything unique
'now that we have the WB part, we can make our macro relative to it
Dim xlMacroUri As URI = PackUriHelper.CreatePartUri(New Uri(GetAbsoluteTargetUri("/xl/workbook.xml", "vbaProject.bin"), UriKind.Relative))
Dim xlMacroPart as PackagePart = xlPackage.CreatePart(xlPartUri, "application/vnd.ms-office.vbaProject", CompressionOption.Normal)
'time we link the vba to the workbook
xlParentPart.CreateRelationship(xlPartUri, TargetMode.Internal, "http://schemas.microsoft.com/office/2006/relationships/vbaProject", "rIdMacro") 'the ID on the macro can be anything as well
'copy over the data from the macro file
Using MacroStream As New FileStream("C:\yourdirectory\vbaProject.bin", FileMode.Open, FileAccess.Read)
MacroStream.CopyTo(xlMacroPart.GetStream())
End Using
'
'now write data into the main workbook any way you like, likely using new Parts to add Sheets

VBA Dynamic Save As, Microsoft Project to Excel

I am trying to create a macro that will export a Microsoft Project file into an excel file. Through the use of macro recording I have got a line of code that accomplishes this using the export wizard, but I want the file path and file name to be dynamic so I can use this macro on different projects. I have been searching many other threads and the Microsoft website with no luck. Is this possible?
Here is what I have:
sub formatAndSave ()
FileSaveAs Name:="C:\Users\XXXXXX\SharePoint\Projects\ProjectType\HxH\myProject.xlsx",_
FormatID:="MSProject.ACE", map:="myMap"
end sub
One idea I tried was:
Active.Workbook.SaveAs FileName:=Title
Any help would be very much appreciated!
For the sake of simplicity, let's assume for all answers below your project is located at c:\projects\myProj.mpp
I think you're after the string replace function. Something like:
Dim excelFilePath As String
excelFilePath = Replace(ActiveProject.FullName, ".mpp", ".xlsx")
Debug.Print excelFilePath
'the output would be c:\projects\myProj.xlsx
If you're unfamiliar with string manipulation in VB/VBA, just search the web for "VBA string manipulation". Microsoft has a decent article here: https://msdn.microsoft.com/en-us/library/aa903372(v=vs.71).aspx
A few other things that may be handy for you are these variables:
ActiveProject.FullName 'shows full path & name, so you'd get "c:\projects\myProj.mpp"
ActiveProject.Path 'shows just the path, so you'd get "c:\projects\"
ActiveProject.Name 'shows just the file name, so you'd get "myProj.mpp"
Finally, one caveat I've seen is that the ActiveProject.FullName and ActiveProject.Name variables may or may not provide the file extension depending on your local windows environment settings. I've observed that if Windows Explorer is configured to hide file extensions, then these variables also withhold the extension; if Explorer is configured to show them, then they are provided in the variables. Make sure your code is robust to both cases, or make sure you have control over the environment where you code will run.

Excel 2007 VBA use string variable value in object variable

Good afternoon guys!
I looked around, but I'm not finding anything that addresses my particular issue, so I'll do my best to explain.
Specs:
Excel 2007, VBA, Outlook 2007
Okay, so I've been reworking some scripts that I created to automate our reports in Excel / Avaya CMS. For the past few years I've been the sole person doing our reports, so it wasn't ever necessary to set things up on anyone else's computers. However, things are changing and I'm in the process of updating the scripts / training others to use them. At the moment, when I put my scripts on their computer, I have to go into the VBA code and manually set every reference to their own relative folder paths / outlook folder paths. Painless enough, except when I do any type of changes to the scripts and have to go through the whole process again on each computer.
So this was my solution: Create a config worksheet on the automated reporting workbook, on that config worksheet store the file paths, and in the code simply use variables to reference the config worksheet. This should make it as easy as setting the variables once from the config on a new computer without having to touch any of the lines of code.
Problem: At midnight there is data that is emailed to us from another office. We use Outlook at this office, so I've simply been having it go to the folder specified in the scripts, download the attachments, and then use the downloaded data for the reports. Since everyone sets up their own outlook folders, the paths inside of outlook are different for each user. Since VBA is accessing a worksheet to grab the config information from a cell, it's returning the path for Outlook folders as a string value. However, the outlook folder variable is of Object type, and so it doesn't allow me to use the string variable as it's value, even though the string itself is the actual value the object needs (just not as a string). So is it possible to convert the string value to a value that can be used in the Object variable?
Worksheet Config Cell Value (B5)- The String Value
outNamespace.Folders("Mailbox - Some Guy").Folders("Reports").Folders("ImportantData")
Code:
'Config tab
Dim serverConfig As Worksheet
Set serverConfig = Sheets("CONFIG")
Dim dirOutlookData As String
dirOutlookData = serverConfig.Range("B5").Value
Dim outFolder As Object
Set outFolder = dirOutlookData
Any ideas? Since the string that's returning for dirOutlookData is the value needed for the object variable value, how can I convert the value from the string variable so it can be used in such a way?
Thanks in advance.
Seems too convoluted a solution. Nobody could share their VBA.
In the example provided
outNamespace.Folders("Mailbox - Some Guy").Folders("Reports").Folders("ImportantData"
you could instead use this directly in the VBA
Set mailboxFolder = outNamespace.GetDefaultFolder(olFolderInbox).Parent
You now have the "Mailbox - Some Guy" folder in a generic way not needing to specify "Some Guy".
Set myFolder = mailboxFolder.Folders("Reports").Folders("ImportantData")