VBA SOLDIWORKS PackAndGo save modified assembly - vba

I've run into a problem while trying to automate SOLIDWORKS API VBA PackAndGo.
The order of action I take are:
Programmatically open an assembly
Programmatically modify this assembly and it's components while renaming the modified components
Programmatically engage pack and go
The unexpected problem is that the exported components have a correct / changed filename (as expected and as intended) but the actual models are the original none modified ones. This is something that I've only come across while trying to programmatically engage PackAndGo. When I do this routine manually from this modified assembly - the models that get renamed and exported are the actual new / modified ones.
My question is: "Why does this happen and how do I make it export teh models from active model?"
The code without the renaming routine etc. that I have written is:
Sub PackAndGo ()
'Set variables
Set swPackAndGo = swRootAssembly.Extension.GetPackAndGo
'Pack And Go
With swPackAndGo
.IncludeDrawings = True
.SetSaveToName True, OutputDirectory
.GetDocumentNames DocumentNamesArray
.GetDocumentSaveToNames DocumentSaveToNamesArray, 0
'Here I do the renaming of components in DocumentSaveToNamesArray
.SetDocumentSaveToNames DocumentSaveToNamesArray
.FlattenToSingleFolder = True
End With
'Pack and go
swRootAssembly.Extension.SavePackAndGo swPackAndGo
End Sub
Maybe I'm missing some additional method or function to make it copy the opened / active assembly components, rather than ones from the hard drive which are in fact the same models, but are not modified or altered in any way.
A simple example would be that I programmatically open a brick that's 20mm long and then programmatically change it's length to 50mm. Now I expect packandgo to save / export this 50mm long one but what it in fact does when run programmatically is export the same 20mm long brick, but with a different filename (again, different filename is what is expected)

Related

Is there any benefit to opening a file in VBA using a Sub vs using FollowHyperlink

So a little background - I have been using VBA for a few months now to write a program to speed up some of the work I do. This involves opening files, and at the moment I have been opening files with Autocad using the following sub:
Sub OpenAutocadFile(AutocadFile)
If AutocadVariable Is Nothing Then
Set AutocadVariable = CreateObject("AutoCAD.Application")
If AutocadVariable Is Nothing Then
MsgBox "Could not start Autocad"
Exit Sub
End If
Else
Set AutocadVariable = GetObject(, "AutoCAD.Application")
End If
Set AutocadApp = AutocadVariable
AutocadApp.Visible = True
AutocadApp.Documents.Open (AutocadFile)
End sub
Not perfect I know, but it works the majority of the time.
I also have been opening PDF files using:
ActiveWorkbook.FollowHyperlink(PDFFile)
Now my question is, is there any advantage to using one method or the other for opening a file in VBA?
I already know that with the dedicated sub, you can specify what program you want to use whereas with the hyperlink method it uses the default one.
So other than that am I missing something? Does one run faster than the other? Is one method preferable for certain file types whereas the other is for other file types?
The difference is functional, as they do different things to get similar results.
The CreateObject method uses an explicit application to open the reference, while FollowHyperlink uses the default application registered for that protocol, and passes the reference to that.
Which one is preferable is up to the developer, as sometimes you want user expected behaviour ("Open a PDF in my fave PDF viewer") and other times you may not want this. For example, maybe you know that the "open with" handler for this system doesn't do what you or the user wants.
Whether one is faster than the other isn't actually that important, as they are intended for different use cases.

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.

Permanently Save Variables with VBA?

One of my many Userforms in Excel uses file paths to locate files to copy,move,delete depending on the situation. The majority of these file locations are always in the same directory and i am looking for a permanent way to store the file paths like a configuration file or settings files so VBA will allows look in the same place.
I was thinking about adding the String paths to the hidden personal workbook and reference each cell when assigning the variable but i develop on my machine and then rollout to other PC and i won't to avoid overwriting them.
I've heard text files can be used or SaveSettings() method which i've used before.
What would be the best way to accomplish this task and is it worth doing?
If it is for all users/different pcs then I can think of two ways.
Way 1
Store the values in Excel Settings.
Use the Application.DefaultFilePath to store the path and then read from it later. For example
Sub StorePath()
Application.DefaultFilePath = "C:\Temp"
End Sub
Sub GetPath()
MsgBox Application.DefaultFilePath
End Sub
Way 2
Store the values in the registry. See this small TUTORIAL I wrote couple of years ago.

VBA - force excel to save in custom format

For a project at work i would like to allow the user to create an export of data to be saved for a single project, since it will not be possible to save my main workbook for each project.
I have created a function that exports the data to another workbook, but now i want to make sure that the user won't change the exported data directly (By setting another file format, i think the users would think more about opening the workbook, and therefore not do it by "accident")
So my question is:
Can i force the user to save the file as a .clg file?
Edit:
I solved the problem by saving the file with .SaveAs and specifying the format as "51" (The same as .xlsx"). I used GetSaveAsFilename to allow the user to decide the location (i.e. the project folder), and only browse for .clg files.
Dim sFullName As String
sFullName = exportFile.Application.GetSaveAsFilename(thisFile.Sheets("Project information").Cells(1, 2).Value, "Export files (*.clg),*.clg", , "Choose export location", "Export")
If Not Len(sFullName) = 0 Or sFullName = "False" Then
exportFile.SaveAs Filename:=sFullName, FileFormat:=51
End If
exportFile.Close
If someone wants to use Mr. Monshaw's approach, one way to go is to create a class module, which has a variable withevents - which means that any event that fires in the variable, fires in your module.
Public WithEvents wbk As Workbook
Just remember to keep the instance of the class in memory, for example by adding it to a collection.
Another way to use the BeforeSave is to dynamically write the code, see http://www.ozgrid.com/forum/showthread.php?t=163903
Is 'clg' a format you use? or just a random not xls/x extension?
If the file does need to be viewed and viewed in excel (guessing your not exporting windows catalogue files?) then changing the extension might not be the best move.
If you create your export using VBA, then you can automate some things to make it more apparent to the users that they should not be editing the data.
The Workbook.SaveAs method has the option for "ReadOnlyRecommended" which will inform the user that the workbook should be opened read-only when opening it. (its optional though, so they could ignore it)
Assuming the data is always read-only you could also lock the workbook so that no changes can be made.
Update
If you want to save an Excel Workbook with a custom extension (and not as a custom format) then using the Workbook.SaveAs method will work. ex: ThisWorkbook.SaveAs "Report.clg"
You'll either need to have your export code do this for you, or if its a more manual process you can just create a macro with a button to invoke the save-as for you instead of using the standard save-as dialogue.
If you want to save as a custom format, and it is not one of the ones supported by Workbook.SaveAs (supported formats) you will have to do as #Mr.Monshaw suggested and watch for the onbeforesave and generate the file manually. (unlikely someone has done an excel to windows catalogue converter)
im not sure what the constant for clg would be but the fileformat property of SaveAs in vba would allow you to decide what format to save in
i saw a clever solution to something similar to this if you can find the fileformat, just add a macro to your book with a workbook event like this:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Call SaveAsCLG(SaveAsUI) 'set save type
Cancel = True 'cancel user save
End Sub
that will override a user save-as request

Batch add a macro to word documents?

I have several hundred .doc word documents to which I need to add a macro which runs when the .doc file is opened and creates a header for said document based on the file name. Is there a way to do this as a batch? I have been individually opening each document and going into visual basic --> Project --> This Document then inserting a .txt file which contains the code. Is there a fast way to do this for multiple documents?
As a learning exercise, put this into the "ThisDocument" part of Normal (the Normal.dot template) in the VBE
Open a word document and watch what happens.
I don't think you need to put your code in every single file, I think you should be OK with using the Document_Open event in Normal.dot.
Just make sure it shows up as a reference in your word documents that you open but I don't see why it wouldn't
If you absolutely need it in every file then it can be done but the problem is if you make one small change to the code, you have to go through all this again. The idea with code is to write it once, use it many times.
You can write VBA code that alters the VBA code in other documents, but you need to "Trust access to the VBA project object model" in the Trust Centre options. This could open you up to viral code if you download Word documents with malicious VBA code in them. What you want to do, essentially, is write a VBA virus. There are legitimate reasons for doing this, and also malicious ones, I leave the ethics of the uses of these techniques up to the user. Knowledge itself is not malicious.
Here's the meat, you will need to write your own code to loop through the documents and possibly save them as .docm files.
Sub ReplaceCode()
Set oDoc = ActiveDocument
Set oComponents = oDoc.VBProject.VBComponents
For i = oComponents.Count To 1 Step -1
If oComponents(i).Type = 100 And oComponents(i).Name = "ThisDocument" Then
With oComponents(i).CodeModule
.DeleteLines 1, .CountOfLines
.AddFromFile "C:\ThisDocument.cls"
End With
End If
Next i
End Sub
Also, if you create your code file by exporting from VBA, you will need to remove this from the top of the .cls file:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Personally, I would drive this from Excel, maybe using a worksheet to hold a list of the files or locations to update, and another sheet for the code to populate with a list of files updated.