workbooks.close does not work for me - ms-access

Hope someone can help with my following problem.
I want to make sure a specific workbook is closed before It gets an update.
for that I was planning to start with.
Private Sub Command1_Click()
workbooks("workbookname.XLSM").close Savechanges = False
End Sub
I also tried
workbooks("workbookname.Xlsm").close
Both i have run separately and both give me Error code 9.
The specific file will always be on the desktop of the user.
I thought it might have something to do with my references so I checked and have the following references turned on. (some for other specific reasons).
Visual Basic For Applications
Microsoft Access 16.0 Object Library
OLE Automation
Microsoft DAO 3.6 Object Library
Microsoft Excel 16.0
Object Library Microsoft Scripting Runtime.
Really hope someone can help me with this. I've been surfing quite a large number of forums but no where i could find the same problem or solution.
w.k.r. Drac.

You have to check to see if it's open, and reference the open object properly. The function below (which I picked up off SO somewhere), returns a true/false value about the file in particular:
You would use it as such:
Private Sub Command1_Click()
Dim xls As Object
If IsWorkBookOpen("C:/Users/Desktop/Workbook.xlsm") = True Then
Set xls = GetObject("C:/Users/Desktop/Workbook.xlsm")
xls.Close True
Else
'do stuff if closed
End If
End Sub
Function:
Function IsWorkBookOpen(FileName As String)
Dim ff As Long, ErrNo As Long
On Error Resume Next
ff = FreeFile()
Open FileName For Input Lock Read As #ff
Close ff
ErrNo = Err
On Error GoTo 0
Select Case ErrNo
Case 0: IsWorkBookOpen = False
Case 70: IsWorkBookOpen = True
Case Else: Error ErrNo
End Select
End Function

Related

How do I detect the presence of objects using VBA in Access 2016?

I have an Access 2016 application that gets distributed to many users who are not sophisticated users. They usually have to install the MS Runtime for Access. Despite clear directions, too many users still find that the application will not open. It appears that early bound objects are not present on the system. With bound objects not present no code ever loads or runs, so it is not even possible to give a good error message.
I am now attempting to write a small program in which all the objects needed by the application are late bound, thus being able to say which modules are missing, if any. What I am finding though is that my method for detection is failing even when I KNOW the object is present. The code below is an example of one test for a required object. This test always fails and I cannot figure out why. I have about 7 of these. Three seem to work correctly, but the others do not. Is there some different way I should be coding the "CreateObject"?
Private Sub btnOffice_Click()
'Office FileDialog MSO.DLL Microsoft Office 16.0 Object Library
Dim obj As Object
On Error GoTo xyzzy
Set obj = CreateObject("Office.FileDialog")
lblOffice.Caption = "Office module present"
Exit Sub
xyzzy:
lblOffice.Caption = officeWarning
MsgBox Err.Description
End Sub
You're trying to detect broken References. Here's a procedure to check for and report broken references:
Sub CheckReferences()
Dim ref As Reference
For Each ref In References
If ref.IsBroken Then
MsgBox "Broken reference detected: " & vbCrLf & ref.Name & vbCrLf & ref.FullPath, vbOKOnly + vbCritical, "Broken Reference"
End If
Next ref
End Sub
The problem here is that the file dialog is not available as a separate COM object, and thus you can’t use CreateObject() to create such an instance.
However, if you plan to distribute your application without an office reference (and I think you safe to do so – even with runtime), then you can change the FileDialog code to late binding:
Eg this:
Dim f As FileDialog
Set f = Application.FileDialog(msoFileDialogFilePicker)
f.Show
MsgBox "file choose was " & f.SelectedItems(1)
Becomes this:
Dim f As Object
Set f = Application.FileDialog(3)
f.AllowMultiSelect = True
f.Show
MsgBox "file choosen was " & f.SelectedItems(1)
So in your case, the filedialog is not available as a separate COM object, but you can still as above shows adopt late binding anyway. However, in my experience, it IS safe to distribute the runtime with a office reference and thus at least for the office dialog you don't need late binding. For reliability, since in the case of FileDialog the late binding code is not a big deal, then I would continue distribution without the office reference for the FileDialog and use the above late binding.

Upgrade Access 2000 to 2010 then 2016 VB question

Help please...I have successfully upgraded from Access 2000 to 2010 then to 2016 with no compile errors however I have an exe file within a form in the VB code and it doesn't run anymore or send an error message. The project is a weighbridge and has been operating on access 2000 for 15 or more years with many changes to the design, where the exe file captures the data from the weighbridge "signal" box and sends it to my form. This exe no longer works in Access 2010 (the go between program during upgrade) or in Access 2016. This is crucial to the project, I no longer have the original code in VB or a copy of VB on my computer although I do have a copy in a text file left by the original programmer. Can anyone tell me Why Access 2016 does not acknowledge this exe. Is there a reference that needs to be clicked? I am lost.
The code is
Private Sub Form_Load()
On Error GoTo Err_Form1
Select Case strDocName
Case "GetGrossWeight"
Set objFrmCtrl = Forms!ConsignmentsIN.GrossWeight
Warning.Caption = "Get Gross Weight In"
Case "GetTareWeight"
Set objFrmCtrl = Forms!ConsignmentsContractIN.TareWeight
Warning.Caption = "Get Tare Weight In"
Case "GetGrossWeightcontract"
Set objFrmCtrl = Forms!ConsignmentsContract.GrossWeight
Warning.Caption = "Get Gross Weight In"
Case "GetTareWeight"
Set objFrmCtrl = Forms!ConsignmentsContract.TareWeight
Warning.Caption = "Get Tare Weight In"
End Select
OpenEXE
Exit_Form2:
Exit Sub
Err_Form1:
MsgBox Error$
Resume Exit_Form2
End Sub
Private Sub OpenEXE()
On Error Resume Next
GrossValue = Shell("c:\weighbr\auto\Weight.exe", 6)
If Err.Number = 53 And GrossValue = 0 Then
MsgBox "Can't find program 'Weight.exe'", vbInformation, "Alert"
End If
' ...
End Sub
According to the documentation for SHELL:
Runs an executable program and returns a Variant (Double) representing the program's task ID if successful, otherwise it returns zero.
Your code gets a task ID, not the result of executing the .exe program (if nothng else prevents execution). So, you shouldn't expect, in any case, to get a value generated by this program.
You should use the debugging tools to step into this Sub and actually figure out what it does.
Check if Alternative to Call Shell() ? (2000) can help you out, and also Access 2000 to 2002 (Shell command).
It seems that the Shell function might have changed a looong time ago.

Microsoft VBScript compilation error: Expected end of statement

I am trying to insert some records into MS Access Table with the help of below VB Script. But when am trying to execute it, it's throwing Compilation error: Expected end of statement. Could someone please help me figure out where am I going wrong.
Private Sub Form_Click()
Dim dbs As DAO.Database
Dim DbFullNAme As String
DbFullName = "D:\G\Diamond\FINAL MS-Access\MS-Access project.accdb"
Set dbs = OpenDatabase(DbFullName)
dbs.Execute "INSERT INTO [2014_Status] ( Prompt, Project_Name, STATUS,Release_Name )SELECT RoadMap.SPRF_CC, RoadMap.SPRF_Name, RoadMap.Project_Phase,RoadMap.Release_Name FROM RoadMap WHERE (((Exists (select 1 FROM [2014_Status] where RoadMap.SPRF_CC = [2014_Status].[Prompt]))=False));"
dbs.Close
End Sub
VBScript (as opposed to VBA or other dialects) does not support typed Dims. So
Dim dbs As DAO.Database
Dim DbFullNAme As String
need to be
Dim dbs
Dim DbFullNAme
VBscript has no native OpenDatabase() function. You need to use ADO to connect to your Access 'database'. First create a connection
Set dbs = CreateObject("ADODB.Connection")
Then determine the connection string and
dbs.Open cs
The rest of your code should work.
Update wrt comment:
The error message:
D:\G\Diamond\FINAL MS-Access\query1.vbs(2, 9) Microsoft VBScript compilation error: Expected end of statement
prooves that the OT tried to write a VBScript (the addition of the misleading vba/access tags is (C) Pankaj Jaju).
So lets break down the real reason why this code doesn't work.
You copied and pasted Visual Basic for Applications(VBA) into a .VBS(Visual Basic Script) file and expected it to work, I assume.
The problem with this is that VBA and VBScript are slightly different languages. Review the info section for both tags on stackoverflow when you get the opportunity.
For now lets just patch your code and maintain your DAO object so you don't have to reconstruct your Database usage with ADODB.
ExecuteInsert
Sub ExecuteInsert()
Dim dbs, DbFullName, acc
Set acc = createobject("Access.Application")
DbFullName = "D:\G\Diamond\FINAL MS-Access\MS-Access project.accdb"
Set dbs = acc.DBEngine.OpenDatabase(DbFullName, False, False)
dbs.Execute "INSERT INTO [2014_Status] ( Prompt, Project_Name, STATUS,Release_Name )SELECT RoadMap.SPRF_CC, RoadMap.SPRF_Name, RoadMap.Project_Phase,RoadMap.Release_Name FROM RoadMap WHERE (((Exists (select 1 FROM [2014_Status] where RoadMap.SPRF_CC = [2014_Status].[Prompt]))=False));"
dbs.Close
msgbox "done"
End Sub
Changes made.
Blocked your dim'd variables and removed As *** statements for vbscript compatibility
Set an access object so you could maintain the remainder of your code.
Added the acc.DBEngine. before OpenDatabase with additional parameters.
Renamed your Sub from Form_Click to ExecuteInsert, then placed ExecuteInsert at the top of the code so that the vbscript activates the sub. If you just place a sub in a vbscript file, it will not necessarily run, you have to activate it directly.
This code is tested and functions. Best of luck to you.
Adding to Ekkehard.Horner
http://www.csidata.com/custserv/onlinehelp/vbsdocs/vbs6.htm
VBScript has only one data type called a Variant. A Variant is a
special kind of data type that can contain different kinds of
information, depending on how it's used. Because Variant is the only
data type in VBScript, it's also the data type returned by all
functions in VBScript.

Code to Kill current Excel file, then Export to new Excel file without opening output file

I have a database that is linked to a few others. The db in question has some script that exports a table to an Excel ".xlsx" with a name that is linked to other databases. Basically data entry is done in one db and then the other db pulls in the information live so we have real time updating.
However, after the kill sequence completes and the new file is exported, the Excel file opens up. This causes a problem with the second db not being able to see real time updates since the new export file does not actually overwrite the previous since the previous has opened automatically. I need help telling the Excel export files not to open.
I know I should Dim the file name but I haven't :-).
Below is the code, any help is much appreciated.
Private Sub Form_Activate()
'Delete Existing File First; then create new
On Error Resume Next
Kill "\\ct13nt003\MFG\SMT_Schedule_Files\SMT Line Progress Files\SMT2Updated.xlsx"
On Error GoTo 0
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "SMT2Export", "\\ct13nt003\MFG\SMT_Schedule_Files\SMT Line Progress Files\SMT2Updated.xlsx", True
Going out on a limb here since I don't really do VBA in Access but I do a lot with Excel so try something like:
Private Sub Form_Activate()
Const xlFileName as String = "\\ct13nt003\MFG\SMT_Schedule_Files\SMT Line Progress Files\SMT2Updated.xlsx"
Const shortFileName as String = "SMT2Updated.xlsx"
Dim xlApp As Object 'Excel.Application
Dim xlWb as Object 'Excel.Workbook
'Delete Existing File First; then create new
On Error Resume Next
Kill xlFileName
On Error GoTo 0
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "SMT2Export", xlFileName, True
'Get the Excel Application
Set xlApp = GetObject(,"Excel.Application")
'Get the specific workbook
Set xlWb = xlApp.Workbooks(shortFileName)
'Close the workbook
xlWb.Close
'Quit Excel (if needed)
'xlApp.Quit
'Clean up
Set xlWb = Nothing
Set xlApp = Nothing
End Sub
Subscript Out of Range Error
Use the file's name instead of the full path with the xlApp.Workbooks method, per revision above.
There is another potential reason for this error, but this is the most likely.
Reading through your scenario, I'm stumped since I've never had that kind of problem with "Killing" a file. Maybe like another users suggested, you should turn off "On Error Resume Next", at least until you figure out why this error is happening.
Another suggestion would be to try a different deletion method, like
myFSO.DeleteFile "\\ct13nt003\MFG\SMT_Schedule_Files\SMT Line Progress Files\SMT2Updated.xlsx"
That code has On Error Resume Next just before Kill xlFileName. That means if the Kill fails for any reason, it will fail silently.
I have no idea whether that issue contributes to your problem, but suggest you try it this way instead.
'Delete Existing File First; then create new
'On Error Resume Next
If Len(Dir(xlFileName)) > 0 Then
Kill xlFileName
Else
' xlFileName does not exist; no Kill required
End If
'On Error GoTo 0

Access macro to read emails from MS Outlook

I have a macro in Access that connects to the running instance of MS Outlook.
The macro had been working, until last week when I started receiving the error: Activex component can't create object whenever I ran the macro.
Here's a piece of the code and where it's currently failing:
Function GatherDailyStats()
Dim oOlAp As Object, oOlns As Object, oOlInb As Object
Dim oOlItm As Object
'Dim FileName As
Dim i, j As Integer
Dim strDir1 As String
Dim strDir2 As String
'~~> Get Outlook instance
Set oOlAp = GetObject(, "Outlook.Application") '--**THIS IS WHERE IT FAILS**
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox).Folders.Item("Daily Stats")
'~~> Check if there are any actual unread emails
If oOlInb.Items.Restrict("[UnRead] = True").Count = 0 Then
MsgBox "NO Unread Email In Daily Stats folder"
Exit Function
End If
Nothing has changed in the code since I created it and tested it thoroughly.
Update: I just tested the same application on a different computer and it worked perfectly there.
Here is a KB article about the ROT and how Office applications by design don't register until their start up sequence has finished. You may be seeing an issue that was always there, just never ran into it before for whatever reason.
Lifted from this discussion you may want to try adding a fall back to make sure that the application is running:
On Error Resume Next
Set objOutlook = GetObject(, "Outlook.Application")
If Err.Number = 429 Then
Set objOutlook = CreateObject("Outlook.Application")
End If
From that same discussion it is important to note that Outlook 2010 apparently has some kind of issue with registering in the ROT when not started in Administrator mode.
Apparently there is a work around that someone has posted which includes:
...if you assign the Everyone group full rights to the Office install
directory it will then work.
Not sure that is the greatest idea but it is a known issue with Office 2010.
EDIT: here is one last resource.
GetObject will throw an error, if the application isn't running. You need to check for this:
On Error Resume Next
Set oOlAp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then Set oOlAp = New Outlook.Application
Alternatively, you could just create a new instance of your object:
Set oOlAp = CreateObject("Outlook.Application")
Using CreateObject to create a new instance will, of course, increase resource load in cases when an object of same type was already initialized. Saying it differently, to increase performance and lower use of system resources, better use the first suggested solution.
Firstly, always use CreateObject when creating an instance of the Outlook.Application object - Outlook is a singleton, so only one instance will ever be running for the logged in user.
Secondly, what are the versions of Outlook and Access? Are they all the same version>? If not, are they both 32 or 64 bit?