Beginsave/Endsave

Beginsave/Endsave

Anonymous
Not applicable
1,618 Views
25 Replies
Message 1 of 26

Beginsave/Endsave

Anonymous
Not applicable
I think my brain is probably just in weekend mode already, this should be so easy but I just can't see it.

What I want to do is to is to determine whether a drawing was successfully saved. If it was not saved, it's name is removed from a list (Excel).

So I import the list from Excel into an array and sort it. And then I'm stuck. Sure I can find out if the number of the drawing is in the list, but that doesn't help me.

What parameter can I use to test whether the drawing has been saved or not?

Also, I'm guessing I want to use the Endsave event, as I want to be sure it has been saved (or not).
0 Likes
1,619 Views
25 Replies
Replies (25)
Message 2 of 26

Anonymous
Not applicable
you might could check the drawing lastmodified propertywith tools ref microsoft scripting runtime
0 Likes
Message 3 of 26

Anonymous
Not applicable
Tertiacb

From The AcadDocument_BeginSave Event module, you could write directly to a text file or write to your spread sheet. Is that an option?

I'm not sure exactly why you are doing this but you could write out the username and time of save I'm sure

ML
0 Likes
Message 4 of 26

Anonymous
Not applicable
Yep,

I just did a simple test; whenever I click save, this is returning the username

So, let me know what you need to do; if you want to write to a .txt file, I can do that in not time for you.

Private Sub AcadDocument_BeginSave(ByVal FileName As String)

Dim WshNetwork As Variant, Username As Variant
Set WshNetwork = CreateObject("WScript.Network")
Username = WshNetwork.Username

MsgBox Username

End Sub
0 Likes
Message 5 of 26

Anonymous
Not applicable
Thanks for the replies!

OK, to get down to details.

I give users a list of drawing numbers to select from when they start a drawing. This list is generated from an Excel sheet. The drawings already used must not appear in the picklist. (And I can't delete them from the original spreadsheet.) In order to do this, I write the selected drawing number to a different spreadsheet. When the user opens AutoCAD to select a new drawing, my program compares the original drawings numbers spreadsheet with the used numbers spreadsheet and filters out the already used numbers so as not to display them again.

But now the problem is, what if the user doesn't save the drawing? Then I have to roll back and remove the picked number from the used numbers spreadsheet, so that it will be displayed again the next time a new drawing is started.

OK so there are several solutions.

I could search for the drawing number in the folders where drawings are stored. This is likely to be pretty time-consuming as drawings can get saved in any one of several folders.

What I am trying to do is to remove the drawing number from the used numbers spreadsheet if the drawing is saved, but I don't know how to establish whether the drawing had actually been saved or not.

The same problem applies should I get the program to only add the used number to the used numbers spreadsheet upon saving of the drawing, I still need to know whether the user saved the drawing. Besides, then the user may be busy on the drawing for a whole day before the drawing number is removed from the picklist, and we are talking 20+ drafties using the same project...

Oh, by the way, I appreciate the Username script - I have a field called "Drawn By" which I want to use to save the draftie's name, and using a computer-generated name is always more accurate than a typed name...

Thanx!
Tertia
0 Likes
Message 6 of 26

Anonymous
Not applicable
Hey Tertia
YW.

Ok, that explains it a little better for sure.

So, if a user saves a drawing, is that absolute evidence that the project number is in use?

Are you using the acad.dvb file that holds all of the ACAD App level and Drawing Level events?

If you decide that the Begin or End Save Event is the way to go then we could have ACAD do the excel part for you or to really simply it; I think the easiest way to take it is to (using the acad.dvb file) simply write code in that event to one file on the serve.

With The FSO (FileSystemObject) in VBScripting, we can write one line at a time to log each username, saved file name and time of save.

In this scenario, we would just be keeping a log of save events throughout the day.

However, if the user saves 35 times a day, do you really want it written 35 times?

So, then, in that case, may be we could assign the first save event to a variable, write it out, then if the time of the each save thereafter = the time of the very first save, exit sub or something like that.

So, the first thing I guess is to see if you are using the acad.dvb which automatically loads with ACAD?
If so, is it the save event that you are definitely looking for?
If so, do you think just writing to a text file will suffice?

In Excel, you can even automate the process of importing the text file as external data and how it appears after import.

May be that is a good idea; log the save (once a day) of each drawing, then at the end of the day, week, whatever, have a macro in your spread sheet that will bring in the text file.

From there, you can use Vlookup or something like that to compare the results in Excel.

Ok, well, I hope this helps

I will wait to see what you decide, hopefully I can be of assistance.

ML
0 Likes
Message 7 of 26

Anonymous
Not applicable
Hey ML

Thanks for your input so far. This sounds promising.

I guess there is more than one object to the exercise. Yes, evidence of the drawing/project number being in use is one of them. Providing a picklist of drawing numbers not in use, for a user creating a new drawing, is another. The latter is what the focus is on right now.

Yes, the .dvb loads with AutoCAD. Actually I have split it into two .dvb's, the first dealing with providing the picklist and setting up the workspace for starting a new drawing, the other to do whatever has to be done when the user exits the drawing. And these live on the server and are referenced by the AutoCAD users.

Unless I do something like searching folders for existing drawings to make sure they were actually saved, which I don't want to do due to the time consumption, I guess the Save event is the only other alternative?

A text file may suffice, but as I have to write to-and-fro to Excel files anyway, I had made the decision to do all the datawriting and - storing in Excel on this particular project. Such as, the storage column I want to use to write the Username to, is in the same spreadsheet where I extract the drawing number from. Another consideration, of course, being that I am foreseeing people demanding lists of used drawings etc. in the future, and then it is all neatly stored in Excel already.

Logging the daily save events would probably help, but I am concerned about a scenario like, user A creates a new drawing, accidentally picking the wrong number from the list of drawing numbers. He exits the drawing without saving and creates a new drawing with the correct drawing number selected from the list. User B wants to use the number user A had just discarded, but now the number is unavailable because of having been used by user A. I think making the drawing number available immediately if the drawing is not stored, is necessary. But then, if the FSO writes to a log, that could trigger some event, right?

I have never actually worked with FSO - I know vaguely about it, and saw some script using it, without paying much attention.

You're right, I hardly want all the save events on one drawing number recorded. I only need the first Save recorded. The time and date are not considered of interest right now, although I think knowing when the drawing was started, may be useful. But for that purpose just saving Currdate in a cell on the spreadsheet should suffice.

All of which deals with detail if the drawing was saved. The problem is how to establish if the drawing wasn't saved. so its number can be removed from the list of used drawing numbers. Do you think one can get a reasonable way of establishing that using the FSO?

Thanx!
T
0 Likes
Message 8 of 26

Anonymous
Not applicable
i found this somewhere...

Public Function GetFileInfo(FileName As String, Optional fReturn As String) As String
On Error GoTo err_fInfo

Dim myFSO, myFileObject

Dim lngAttributes As Long 'Attribute Values, explanation below
Dim datCreated As Date 'Date and time the file was created.
Dim datLastAccessed As Date 'Date and time the file was last accessed.
Dim datLastModified As Date 'Date and time the file was last modified.
Dim strDrive As String 'Drive letter of the drive where the file resides.
Dim strName As String 'Sets or returns the name of the file.
Dim strPath As String 'The path of the file, including drive letter.
Dim strSize As String 'The size, in bytes, of the file.

'*)Component values of the Attribute property. Attribute Value Description Access
'Normal 0 Normal file; no attributes are set
'ReadOnly 1 Read-only file Read/write
'Hidden 2 Hidden file Read/write
'System 4 System file Read/write
'Volume 8 Disk drive volume label Read-only
'Directory 16 Folder or directory Read-only
'Archive 32 File has changed since last backup Read/write
'Alias 64 Link or shortcut Read-only
'Compressed 128 Compressed file Read-only

Set myFSO = CreateObject("Scripting.FileSystemObject")
Set myFileObject = myFSO.GetFile(FileName)

If fReturn = "" Then
With myFileObject
lngAttributes = .Attributes
datCreated = .DateCreated
datLastAccessed = .dateLastAccessed
datLastModified = .dateLastModified
strDrive = .Drive
strName = .Name
strPath = .path
strSize = .Size
End With
' return all file info as string
GetFileInfo = "File Information for file:" & vbCrLf & vbCrLf & _
"Filename: " & strName & vbCrLf & _
"Attributes: " & lngAttributes & vbCrLf & _
"Date Created: " & datCreated & vbCrLf & _
"Date last Accessed: " & datLastAccessed & vbCrLf & _
"Date Last Modified: " & datLastModified & vbCrLf & _
"Drive: " & strDrive & vbCrLf & _
"Path: " & strPath & vbCrLf & _
"Size: " & strSize & " Bytes"
Else
Dim vReturn As Variant
Select Case fReturn
Case "DateCreated"
vReturn = myFileObject.DateCreated
Case "DateLastMod"
vReturn = myFileObject.dateLastModified
Case "DateLastAccessed"
vReturn = myFileObject.dateLastAccessed
Case "Size"
vReturn = myFileObject.Size & " Bytes"
Case Else
vReturn = myFileObject.Name
End Select
GetFileInfo = vReturn
End If

Exit_err:
Set myFileObject = Nothing
Set myFSO = Nothing
Exit Function
err_fInfo:
GetFileInfo = Err.Description
Resume Exit_err

End Function ' GetFileInfo
0 Likes
Message 9 of 26

Anonymous
Not applicable
Thanks!

I'm going to try it as soon as I get out of this meeting I have attend, if it doesn't last too long, otherwise tomorrow.

Why can't management fathom that I prefer to talk to my PC rather than people? 🙂

T
0 Likes
Message 10 of 26

Anonymous
Not applicable
Some points to consider.

1. What if the use takes a file name from the list and open a drawing, works
on it without saving for long time (believe me, some CADer rarely hit "Save"
button until he is done with it (for a few hours). By your logic, the file
name is still available for other users (until the first user who takes the
filename saves the drawing). So, other user could take the same file name.
When he saves the drawing, he finds out a drawing with the save name has
just been saved by someone else. I am not sure how the file name list is
provided to users, within Acad? or from a stand-alone app? or from Excel
application? You should not wait until drawing is saved to mark a file name
being taken. It should be when user select a file name from the list, the
file name then is marked as "Taken", you can then have some code to
immediately open the new drawing and save it as the file name. Of course you
need to handle situation, such as if a drawing is cancelled, the file name
could be return to available file name list for reuse... I would do it in
Acad VBA this way:
a. User starts Acad;
b. Click a custom menu/toolbar button to open a VBA form, which present
available drawing file name list in the project (or entinre file name list
with who take which file name...);
c. Once user pick a file name and click "OK", a new drawing is saved to
selected file name. Of couse you can do more here, such as open a specific
template, do neccesary initialization...
d. Update the fiel naame list. That is, set the just selected file name
as "taken" by fill the record's other fields, such as "Drawn By", "Taken
Time"....
e. You can provide a "Release" button on the form, in case a drawing
that takes a file name is cancelled and you want the file name is available
again.

2. Why 2-spread sheets? a simple file name table is just fine with a column,
such as "Taken Time". That is, if blank, the file name is available, if time
is set, it is taken. Of course you can have more columns, like "Drawn By",
"Chcecked By"... However, after your pains-taking effort to make it finally
works, closely to your expectation, you would, very likely, regret that you
chose Excel sheet instead of a database solution. Believe me, something like
this with a sort of document tracking functionalities without database will
not go far, even for a small drafting operation.


"Tertiacb" wrote in message news:5974451@discussion.autodesk.com...
Thanks for the replies!

OK, to get down to details.

I give users a list of drawing numbers to select from when they start a
drawing. This list is generated from an Excel sheet. The drawings already
used must not appear in the picklist. (And I can't delete them from the
original spreadsheet.) In order to do this, I write the selected drawing
number to a different spreadsheet. When the user opens AutoCAD to select a
new drawing, my program compares the original drawings numbers spreadsheet
with the used numbers spreadsheet and filters out the already used numbers
so as not to display them again.

But now the problem is, what if the user doesn't save the drawing? Then I
have to roll back and remove the picked number from the used numbers
spreadsheet, so that it will be displayed again the next time a new drawing
is started.

OK so there are several solutions.

I could search for the drawing number in the folders where drawings are
stored. This is likely to be pretty time-consuming as drawings can get
saved in any one of several folders.

What I am trying to do is to remove the drawing number from the used numbers
spreadsheet if the drawing is saved, but I don't know how to establish
whether the drawing had actually been saved or not.

The same problem applies should I get the program to only add the used
number to the used numbers spreadsheet upon saving of the drawing, I still
need to know whether the user saved the drawing. Besides, then the user may
be busy on the drawing for a whole day before the drawing number is removed
from the picklist, and we are talking 20+ drafties using the same project...

Oh, by the way, I appreciate the Username script - I have a field called
"Drawn By" which I want to use to save the draftie's name, and using a
computer-generated name is always more accurate than a typed name...

Thanx!
Tertia
0 Likes
Message 11 of 26

Anonymous
Not applicable
Hi Tertia,
I'm sorry, been busy all day.

I did see that someone posted an example of VBScripting using FSO and it looks good, however it had attributes and all. That is cool, you can do a lot with Scripting,
Generally, VBScripting code is placed into a .txt file, then you do Saveas a .vbs file.
At which point you can simply double click the file to execute it. I have done some cool script then open acad and do some things. The other cool thing about VBScritping code is that it can be used in VBA as well, as long as you set a reference to the object that you need in VBA.


OK, well in the below example, the first Sub, I am simply writing out the layers to a text file, it will appear on your desktop.

Then in the second example, the file will be read from and assigned to a variable which then will display your layers in a msgbox in VBA.

Ok, that is cool, right? Well, how does that help you?
We would do something similar, only we are writing out an event, such as Save

Now, Tertia, the file I am referring to is not just a .dvb file, it is the acad.dvb file. Are you using that particular file?
Here yiou go, i will attach mine, so that you can see it.
Place it in your ACAD-Support directory, fire up ACAD and it will be automatically loaded.
Then, in the .dvb file, click on Thisdrawing and you will see the events I have coded. If you have not used it, you will find it extremely helpful.
You see, each drawing has document level events, but what are you going to do, write code in every drawing? Of course not. So, The ACAD.dvb file loads automatically on startup and is in The User's VBA environment all of the time, independent of any drawings. In there we can access drawing and app level events. So, it is very important that you use that file, if this is to work properly. You will find it in your support directory, but in mine, there is already examples that I can share with you.

Ok, so after you look at that file, realizing that this can be loaded into each person's support directory, which will load each time they fire up ACAD, you now have all events accessible to each user, all of the time.

Ok, so, once we have that ready, we can then grab the Begin or End Save Event.

With the below code, run it from a Sub in VBA and you will see that we can send ACAD info out to a text file and read it back into ACAD.

We can write directly to Excel and that might make the most sense. Let me ask you , have you written any VBA code in Excel? If you had the code, we can just put it into ACAD-VBA
If not, then I am not sure what to do; I would have to see the spread sheet etc. etc. in order to know precisely what to do.

Ok, well try loading the acad.dvb file, play with that a bit, then try the below code.

There is also a Begin Open File and a New Drawing Event in The App events, if you'd prefer that direction.

Let me know what you decide and we will see if we can go forward.

Tertia, the file would not attachas a .dvb file, so I changed the extension to xls in order to pass it to you
After you download it, change the extension back to dvb and you should be fine

Have a good night
ML

Public FSO As Variant, Username As Variant
Public Dwgname As String
Sub WriteToText()

'This will write the .txt file to your desktop
Dim FSO As Variant
Dim MyFile As Variant
Dim Layr As AcadLayer

Set FSO = CreateObject("Scripting.FileSystemObject")
Set WshNetwork = CreateObject("WScript.Network")

Username = WshNetwork.Username
Dwgname = UCase(Left$(ThisDrawing.Name, Len(ThisDrawing.Name) - 4))
'Dwgname = "Layers"

Set MyFile = FSO.CreateTextFile("C:\Documents and Settings\" & Username & "\Desktop\" & Dwgname & ".txt", True)

For Each Layr In ThisDrawing.Layers
MyFile.WriteLine Layr.Name
Next Layr

MyFile.Close

End Sub

Sub ReadTextFile()

'This will read the .txt file from your desktop into ACAD

Dim Stream As Variant
Dim Textstr As String

Set FSO = CreateObject("Scripting.FileSystemObject")
Set WshNetwork = CreateObject("WScript.Network")

Username = WshNetwork.Username
Dwgname = UCase(Left$(ThisDrawing.Name, Len(ThisDrawing.Name) - 4))

Set Stream = FSO.OpenTextFile("C:\Documents and Settings\" & Username & "\Desktop\" & Dwgname & ".txt")
'Set FSO = Nothing

Textstr = ""

'While there are lines to read, continue on to the end of the file.
'If the file is empty, we will reach the end of the stream and the variable Textstr will be returned as null.
Do While Not Stream.AtEndOfStream
Textstr = Textstr & Stream.ReadLine & vbCrLf 'or VbNewline
Loop
'Set Stream = Nothing

If Textstr "" Then
MsgBox Textstr
Else
MsgBox "The file you selected is empty"
End If

Stream.Close

End Sub
0 Likes
Message 12 of 26

Anonymous
Not applicable
Tertia
It might jus be the resolution on my monitor but it looks like the bottom part of the second Sub says

If Textstr "" Then

Please make sure it says
If Textstr <> "" Then

That means, if textstream (txt file) is not nothing, then assign it to the variable, otherwwise we'd exit the sub

ML
0 Likes
Message 13 of 26

Anonymous
Not applicable
CADger

Have you tried the script that you posted?
I have not yet but it looks interesting.

One thing I have always wanted to be able to do was change the date created and modified attributes of a file.

This way, no one can really tell when you updated a file.
It adds one more layer of privacy.

I think that script will do this

ML
0 Likes
Message 14 of 26

Anonymous
Not applicable
nope i didn't try the routine above.. for some reason i don't have a help file for fso, but i found this

http://www.itechies.net/tutorials/asp/filesystem.html

as you can see datelastmodifed is a read-only property
0 Likes
Message 15 of 26

Anonymous
Not applicable
CAD
I have a ton of help links on VBScripting, I use it all of the time
Here:
Chew on these a bit;
These are 3 of the main objects used in VBScripting.
FSO:
http://msdn.microsoft.com/en-us/library/z9ty6h50.aspx
Wscript:
http://msdn.microsoft.com/en-us/library/2795740w(VS.85).aspx
another biggy
WshShell
http://msdn.microsoft.com/en-us/library/ahcz2kh6
(VS.85).aspx
There are lots of examples as well.
Just copy the code into a txt file, do a saveas .vbs file.
Then you double click The vbs file and off the script goes.
Great stuff.
If you grasp this stuff, then you can start out simple with ACAD; that is, set a reference to The ACAD App and start manipulating ACAD from outside of ACAD
Simple example:
This will open ACAD

Dim Acad
Set Acad = CreateObject("Autocad.Application")
Acad.Visible = True

Also, a free and really great program is called
vbedit
www.vbsedit.com
With that you can debug the code and connect to the objects and properties in the app, such as ACAD, just like you would in VBA

Hope you like
ML
0 Likes
Message 16 of 26

Anonymous
Not applicable
CAD

This is a nice little link, thanks, i will keep that
Still, I do believe there must be a way to manipulate that date.

By the way, i use VBScript code in VBA a lot as well.

ML
0 Likes
Message 17 of 26

Anonymous
Not applicable
Tertiaa
Have you given up?

ML
0 Likes
Message 18 of 26

Anonymous
Not applicable
Hi all,

Thanks for all the advice so far, sorry I'm taking so long about it. Two of our support guys haven't been in the office since Tuesday, so guess who get to do the support. I'm just not getting around to even touching my programming. So far today looks quieter... I just want to sort out an array I managed to mess up and confuse myself with, first, though. Will get back to you soonest.
0 Likes
Message 19 of 26

Anonymous
Not applicable
Hi,

Can't you use the variable DBMOD
I use it to check if a drawing needs to be saved.

When a drawing was saved successfully then the variable
DBMOD is reset to 0
0 Likes
Message 20 of 26

Anonymous
Not applicable
Sounds brilliant, Wouter

I wish these support issues would now just GO AWAY so I can down to real work. I'm e-mailing my work home this weekend, will possibly be able to report back on Monday.

Thanks again everyone for your help! I'd be so lost without you.
0 Likes