Is it possible to make a VBA code that changes the Acces opening mode from exclusive mode to shared mode? I have a code that detects if the Acces was opened in exclusive mode and gives you an error message if it was. Is it possible to make a VBA code that automatically changes the opening mode from exclusive to shared? This is the code I'm using to determine if the user opened the database in exclusive mode or not. I want to put the opening mode change part in the case 70 part, this is the return if the data base was opened in exclusive mode.
Public Function IsCurDBExclusive() As Integer
'Célja: Eldönti, hogy az adatbázis kizárólagos módban van-e megnyitva.
'Visszatérés: 0, ha az adatbázis nem kizárólagos módban van megnyitva.
' -1, ha az adatbázis nem kizárólagos módban van megnyitva.
' Err ha valamilyen probléma lpett fel.
Dim db As DAO.Database
Dim hFile As Integer
hFile = FreeFile
'Dim lngRed As Long, lngOrange As Long
'lngRed = RGB(255, 0, 0)
'lngOrange = RGB(197, 90, 17)
Set db = CurrentDb
If Dir$(db.Name) <> "" Then
On Error Resume Next
Open db.Name For Binary Access Read Write Shared As hFile
'------------------------------------------------------------------------------------------------------------------------------------------------------
Select Case Err
Case 0 'Az az eset amikor megosztott módban van megynitva az adatbázis.
IsCurDBExclusive = False
' MsgBox "Nem kizárólagos!"
Case 70 'Az az eset amikor kizárólagos módban van megynitva az adatbázis.
IsCurDBExclusive = True
MsgBox "Kizárólagos módban nyitotta meg az adatbázist! Használja megosztott módban vagy kérjen segítséget az átállításához!", 0, "Figyelem" 'Ha kizárólagos módban van megnyitva ezt fogja kiírni.
If ActiveWorkbook.ExclusiveAccess Then
ActiveWorkbook.MultiUserEditing
End If
'Form!MENU.BackColor = lngRed
Case Else
IsCurDBExclusive = Err
End Select
'------------------------------------------------------------------------------------------------------------------------------------------------------
Close hFile
On Error GoTo 0
Else
MsgBox "Couldn't find " & db.Name & "."
End If
Related
I'm working at a company as an intern. I never used vba in my life before. I need to display if the MS Access database was opened in exclusive mode at the user's computer. It needs to has some kind of red indicator if the user is opened with exclusive mode in any other case it should display a green indicator. The Access is used in shared mode.
Edit: I found this on a Hungarian page. (link to the page: https://prog.hu/tudastar/101971/access-megnyitasi-opciok-lekerdezese-vba-ban)
Function IsCurDBExclusive () As Integer
'Purpose: Determine if the current database is open exclusively.
'Returns: 0 if database is not open exclusively.
' -1 if database is open exclusively.
' Err if any error condition is detected.
Dim db As DAO.Database
Dim hFile As Integer
hFile = FreeFile
Set db = CurrentDb
If Dir$(db.name) <> "" Then
On Error Resume Next
Open db.name For Binary Access Read Write Shared As hFile
Select Case Err
Case 0
IsCurDBExclusive = False
Case 70
IsCurDBExclusive = True
Case Else
IsCurDBExclusive = Err
End Select
Close hFile
On Error GoTo 0
Else
MsgBox "Couldn't find " & db.name & "."
End If
End Function
I don't know where I should put to try it out, if it even works or good.
Public Function IsCurDBExclusive() As Integer
Dim db As DAO.Database
Dim hFile As Integer
hFile = FreeFile
Set db = CurrentDb
If Dir$(db.Name) <> "" Then
On Error Resume Next
Open db.Name For Binary Access Read Write Shared As hFile
Select Case Err
Case 0
IsCurDBExclusive = False
MsgBox "Shared mode"
Case 70
IsCurDBExclusive = True
MsgBox "Exclusive mode", 0, "Attention"
If ActiveWorkbook.ExclusiveAccess Then
ActiveWorkbook.MultiUserEditing
End If
'Form!MENU.BackColor = lngRed
Case Else
IsCurDBExclusive = Err
End Select
Close hFile
On Error GoTo 0
Else
MsgBox "Couldn't find " & db.Name & "."
End If
End Function
Private Sub Form_Load()
IsCurDBExclusive
End Sub
I managed to make it work. Here is the code guys.
I was able to edit this code and make VBA connect with SAP.
When I make the call the code stops working on the first line of second code - Session.findById... and gives the error
Run time error 424: Object Required
Follow the codes and the error occurs on the commented line in the second code.
Full code of the SAP connection module:
Global Session
Sub SAP_Login(ByVal Transacao As String)
Dim SapGui
Dim Applic
Dim Connection
Dim Session
Dim WshShell
Dim mensagem As String
On Error GoTo DESLOGADO
Set Session = GetObject("SAPGUI").GetScriptingEngine.Children(0).Children(0)
GoTo LOGADO
DESLOGADO:
'Abre o Sap instalado na sua máquina
Shell "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe", vbNormalFocus
'inicia a variável com o objeto SAP
Set WshShell = CreateObject("WScript.Shell")
Do Until WshShell.AppActivate("SAP Logon ")
Application.Wait Now + TimeValue("0:00:01")
Loop
Set WshShell = Nothing
Set SapGui = GetObject("SAPGUI")
Set Applic = SapGui.GetScriptingEngine
Set Connection = Applic.OpenConnection("NEA Dow Prod - ERP Central Component (ECC) (SSO) (001)", True)
Set Session = Connection.Children(0)
Session.findById("wnd[0]").maximize
'DADOS PARA FAZER O LOGIN NO SISTEMA
'On Error Resume Next
'Session.findById("wnd[0]/usr/txtRSYST-MANDT").Text = "800" 'client do sistema
Session.findById("wnd[0]").sendVKey 0
LOGADO:
With Session
.findById("wnd[0]/tbar[0]/okcd").Text = "/o"
.findById("wnd[0]").sendVKey 0
.findById("wnd[0]/tbar[0]/okcd").Text = "/n"
.findById("wnd[0]").sendVKey 0
.findById("wnd[0]/tbar[0]/okcd").Text = Transacao
.findById("wnd[0]").sendVKey 0
'possivel texto de erro sap vai aparecer no excel
mensagem = .findById("wnd[0]/sbar").Text
If mensagem <> Empty Then
Application.StatusBar = mensagem
End If
End With
'ESSA PARTE SAI DO SISTEMA POS A EXECUÇÃO DO CÓDIGO
'Set session = Nothing
'Application.Wait Now + TimeValue("0:00:05")
'connection.CloseSession ("ses[0]")
'Set connection = Nothing
'Set sap = Nothing
End Sub
Second code that makes the call and continues the SAP script (it's on a button):
Private Sub EXTRAIR_Click()
Call SAP_Login("coois")
Session.findById("wnd[0]/mbar/menu[2]/menu[0]/menu[0]").Select 'THIS IS WHERE THE ERROR BEGINS!!!
Session.findById("wnd[1]/usr/txtENAME-LOW").Text = "nd87309"
Session.findById("wnd[1]").sendVKey 8
Session.findById("wnd[0]/usr/tabsTABSTRIP_SELBLOCK/tabpSEL_00/ssub%_SUBSCREEN_SELBLOCK:PPIO_ENTRY:1200/ctxtS_ECKST-LOW").Text = "07062022"
Session.findById("wnd[0]/usr/tabsTABSTRIP_SELBLOCK/tabpSEL_00/ssub%_SUBSCREEN_SELBLOCK:PPIO_ENTRY:1200/ctxtS_ECKST-HIGH").Text = "07062022"
Session.findById("wnd[0]").sendVKey 8
Session.findById("wnd[0]/usr/cntlCUSTOM/shellcont/shell/shellcont/shell").SetCurrentCell -1, ""
Session.findById("wnd[0]/usr/cntlCUSTOM/shellcont/shell/shellcont/shell").SelectAll
Session.findById("wnd[0]/usr/cntlCUSTOM/shellcont/shell/shellcont/shell").ContextMenu
Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").SelectContextMenuItemByPosition "0"
Range("A2").PasteSpecial
MsgBox "Copiado com Sucesso"
End Sub
You have
Dim Session
inside SAP_Login: that variable will "hide" the Global variable with the same name, so when that sub exits the Global is still Nothing. Remove the local variable declaration so only the Global one remains.
I am using the ScriptControl in Access VBA to load the scripts (.vbs files) and execute them for extracting data from a SAP system. For the small data the code works fine.
However, when there is a big data which takes time or stops responding then Access opens a popup window asking me to switch to the app or retry. If I click on retry button or by hand switch to that window, then the script resumes!
Is there any way to tackle this access popup window or a code to press this retry button? Thanks
Mycode:
Open scriptPath For Input As #1
vbsCode = Input$(LOF(1), 1)
Close #1
On Error GoTo ERR_VBS
With CreateObject("ScriptControl")
.Language = "VBScript"
.AddCode vbsCode '>>>>>>>>>>>>>>>> I get this popup window at this line
End With
Tried :
Sub Test()
Dim oSC As Object
Set oSC = CreateObjectx86("ScriptControl") ' create ActiveX via x86 mshta host
Debug.Print TypeName(oSC) ' ScriptControl
' do some stuff
CreateObjectx86 Empty ' close mshta host window at the end
End Sub
Function CreateObjectx86(sProgID)
Static oWnd As Object
Dim bRunning As Boolean
Dim vbsCode As String, result As Variant, Script As Object
Open "\My Documents\\Desktop\x.vbs" For Input As #1
vbsCode = Input$(LOF(1), 1)
Close #1
Set oWnd = CreateWindow()
oWnd.execScript vbsCode, "VBScript" '>>>>>>>>>Gets an Error says "Error on Script page"
Set CreateObjectx86 = oWnd.CreateObjectx86(sProgID)
End Function
Function CreateWindow()
' source http://forum.script-coding.com/viewtopic.php?pid=75356#p75356
Dim sSignature, oShellWnd, oProc
On Error Resume Next
Do Until Len(sSignature) = 32
sSignature = sSignature & Hex(Int(Rnd * 16))
Loop
CreateObject("WScript.Shell").Run "%systemroot%\syswow64\mshta.exe about:""<head><script>moveTo(-32000,-32000);document.title='x86Host'</script><hta:application showintaskbar=no /><object id='shell' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object><script>shell.putproperty('" & sSignature & "',document.parentWindow);</script></head>""", 0, False
Do
For Each oShellWnd In CreateObject("Shell.Application").Windows
Set CreateWindow = oShellWnd.GetProperty(sSignature)
If Err.Number = 0 Then Exit Function
Err.Clear
Next
Loop
End Function
So after lot of headache, I found the solution! The solution is to use waitToReturn. This will make Access VBA wait for the Script to be completed no matter how long it take! Hence, this tackled the problem of Access popup window asking to switch to window or Retry!
Solution code:
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim errorCode As Integer
errorCode = wsh.Run("C:\path\x.vbs", windowStyle, waitOnReturn)
If errorCode = 0 Then
MsgBox "Script successful. "
Else
MsgBox "Script exited with error code " & errorCode & "."
End If
with cases like this you would always try to get the focus via the object you are manipulating, usually it is done by .setFocus or .active.
the below is code that will help you out. I would try the session.setFocus.
Session.ActiveWindow.SetFocus
the below code will also help:
Dim SapGuiAuto As Object
Dim Application As SAPFEWSELib.GuiApplication
Dim Connection As SAPFEWSELib.GuiConnection
Dim Session As SAPFEWSELib.GuiSession
Dim UserArea As SAPFEWSELib.GuiUserArea
' Dim oWindow As SAPFEWSELib.GuiConnection
Dim oUserAreaOfMobileWindow As SAPFEWSELib.GuiUserArea
Dim oGuiSimpleContainer As SAPFEWSELib.GuiSimpleContainer
Set SapGuiAuto = GetObject("SAPGUI")
If Not IsObject(SapGuiAuto) Then
Exit Sub
End If
Set Application = SapGuiAuto.GetScriptingEngine()
If Not IsObject(Application) Then
Exit Sub
End If
Set Connection = Application.Connections(0)
If Not IsObject(Connection) Then
Exit Sub
End If
Set Session = Connection.Sessions(0)
If Not IsObject(Session) Then
Exit Sub
End If
I made a multi-user interface on Excel to write records on a common Excel file using ADO Connection.
I have four users using this interface (different interface file for each user).
It works, until two or more users try to add or edit a record simultaneously.
When that's the case, VBA opens the Excel file in read-only mode right after it tries to open the ADO connection for the last user.
Read-only Excel file opened
My work-around try was to use an ISWORKBOOKOPEN() function to identify when concurrency occurs and then close the file, close the connection, wait a second and then try again:
Application.ScreenUpdating = False
Dim ADODBCONNECT As New ADODB.Connection
Dim RECORDSET As New ADODB.RECORDSET
Dim SQL_FILTER As String
Dim DATABASE As String
' -------- BACKUP --------
Dim oFSO As Object
Set oFSO = CreateObject("Scripting.FileSystemObject")
Call oFSO.CopyFile(Range("SLITTING_DATABASE"), Range("BACKUP_FILENAME"))
' -------- ADIÇÃO DO REGISTRO --------
DATABASE = Workbooks("S41 - Deacro.xlsm").Sheets("DATA SOURCES").Range("SLITTING_DATABASE")
OPEN_CONN:
ADODBCONNECT.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source ='" & DATABASE & "';
Extended Properties='Excel 12.0'"
ADODBCONNECT.Open
If ISWORKBOOKOPEN(DATABASE) = True Then
ADODBCONNECT.Close
Workbooks(DATABASE).Close False
newHour = Hour(Now())
newMinute = Minute(Now())
newSecond = Second(Now()) + 1
WAITTIME = TimeSerial(newHour, newMinute, newSecond)
Application.Wait WAITTIME
GoTo OPEN_CONN
End If
SQL_FILTER = "Select * From [SLIT_INCOME$]"
RECORDSET.Open SQL_FILTER, ADODBCONNECT, adOpenKeyset, adLockOptimistic
RECORDSET.AddNew
RECORDSET!SlittingWO = Workbooks("S41 - Deacro.xlsm").Sheets("INTERFACE").Range("OP_Corte")
RECORDSET!ReelUD = CADASTRO_DE_BOBINAS.REEL_UD_ENTRY
RECORDSET!ReelLenghtm = CADASTRO_DE_BOBINAS.REEL_MTS_IN_ENTRY
RECORDSET!Date = Now
RECORDSET.UPDATE
RECORDSET.Close
ADODBCONNECT.Close
' -------- ATUALIZAÇÃO DOS DADOS NA INTERFACE --------
Call UPDATE_DATA
Application.ScreenUpdating = True
Two other problems occur here:
1 - The workbooks.close seems not to be working when the file opens because of:
Error 9, subscript out of range
2 - If the function is used after opening the ADO connection, it returns true even when the connection has been opened by same user that is checking the file availability.
I copied the function from another question here:
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
Is there a way to detect that the file is being accessed through ADO connection by another user, so I can make a loop to force the last user to wait until the first user's connection is closed?
I know Excel has a lot of limitations when used as database file, but it is the only tool my company provides.
Work-around: created a "locking-flag" file that is opened as input and read mode is locked before the ADO connection is stablished. First user to open the file causes the second one to crash on VBA error 70, which I use to loop the second user through the attempt to open the "locking-flag" file untill the first one closes it.
Application.ScreenUpdating = False
Dim ADODBCONNECT As New ADODB.Connection
Dim RECORDSET As New ADODB.RECORDSET
Dim SQL_FILTER As String
Dim DATABASE As String
' -------- BACKUP --------
Dim oFSO As Object
Set oFSO = CreateObject("Scripting.FileSystemObject")
Call oFSO.CopyFile(Range("SLITTING_DATABASE"), Range("BACKUP_FILENAME"))
' -------- BLOQUEAR BANCO DE DADOS --------
DATABASE = Workbooks("S41 - Deacro.xlsm").Sheets("DATA SOURCES").Range("SLITTING_DATABASE")
LOCKING_FLAG_FILE = Workbooks("S41 - Deacro.xlsm").Sheets("DATA SOURCES").Range("LOCKING_FLAG_FILE")
ErrNo = 0
Do
On Error Resume Next
ff = FreeFile()
Open LOCKING_FLAG_FILE For Input Lock Read As #ff
ErrNo = Err
On Error GoTo 0
Loop While ErrNo = 70
' -------- ADIÇÃO DO REGISTRO --------
ADODBCONNECT.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source ='" & DATABASE & "'; Extended Properties='Excel 12.0'"
ADODBCONNECT.Open
SQL_FILTER = "Select * From [SLIT_INCOME$]"
RECORDSET.Open SQL_FILTER, ADODBCONNECT, adOpenKeyset, adLockOptimistic
RECORDSET.AddNew
RECORDSET!SlittingWO = Workbooks("S41 - Deacro.xlsm").Sheets("INTERFACE").Range("OP_Corte")
RECORDSET!ReelUD = CADASTRO_DE_BOBINAS.REEL_UD_ENTRY
RECORDSET!ReelLenghtm = CADASTRO_DE_BOBINAS.REEL_MTS_IN_ENTRY
RECORDSET!Date = Now
RECORDSET.UPDATE
RECORDSET.Close
ADODBCONNECT.Close
' -------- DESBLOQUEAR BANCO DE DADOS --------
Close ff
' -------- ATUALIZAÇÃO DOS DADOS NA INTERFACE --------
Call UPDATE_DATA
Application.ScreenUpdating = True
It's far away from being an elegant solution, but if excel is the only tool you have, and there are not a lot of users using the interface (in this case, I only have four), this will do the job.
I am encountering a run-time error while using IMAPI. The error:
Adding a file or folder would result in a result image having a size larger than the current configured limit.
It works great for anything that doesn't exceed the type of media in the optical drive, else I get the above.
I saw a post from A_J here that leans toward a possible solution in C#:
fileSystemImage.FreeMediaBlocks = int.MaxValue;
I am looking for help in writing the above, but in 2013 Excel VBA.
Below is a copy of what I'm using:
Option Explicit
Sub TestCDWrite()
Application.DisplayAlerts = False
Dim objDiscMaster As IMAPI2.MsftDiscMaster2
Dim objRecorder As IMAPI2.MsftDiscRecorder2
Dim DataWriter As IMAPI2.MsftDiscFormat2Data
Dim intDrvIndex As Integer
'The Object browser, but not intellisense, presents types for these, but they cannot be used in VBA
Dim stream As Variant
Dim FS As Variant
Dim Result As Variant
Dim FSI As Object
Dim strBurnPath As String
Dim strUniqueID As String
' *** CD/DVD disc file system types
Const FsiFileSystemISO9660 = 1
Const FsiFileSystemJoliet = 2
Const FsiFileSystemUDF102 = 4
'On Error GoTo TestCDWrite_Error
intDrvIndex = 0
strBurnPath = Worksheets("mphoi").Range("AF2")
' Create a DiscMaster2 object to connect to optical drives.
Set objDiscMaster = New IMAPI2.MsftDiscMaster2
' Create a DiscRecorder2 object for the specified burning device.
Set objRecorder = New IMAPI2.MsftDiscRecorder2
strUniqueID = objDiscMaster.Item(intDrvIndex)
objRecorder.InitializeDiscRecorder (strUniqueID)
' Create a DiscFormat2Data object and set the recorder
Set DataWriter = New IMAPI2.MsftDiscFormat2Data
DataWriter.Recorder = objRecorder
DataWriter.ClientName = "IMAPIv2 TEST"
' Create a new file system image object
Set FSI = New IMAPI2FS.MsftFileSystemImage
fsi.freemediablocks=int.maxvalue
' Import the last session, if the disc is not empty, or initialize
' the file system, if the disc is empty
If Not DataWriter.MediaHeuristicallyBlank Then
On Error Resume Next
FSI.MultisessionInterfaces = DataWriter.MultisessionInterfaces
If Err.Number <> 0 Then
MsgBox "Multisession is not supported on this disc", vbExclamation, "Data Archiving"
GoTo ExitHere
End If
On Error GoTo 0
MsgBox "Importing data from previous session ...", vbInformation, "Data Archiving"
FS = FSI.ImportFileSystem()
Else
FS = FSI.ChooseImageDefaults(objRecorder)
End If
' Add the directory and its contents to the file system
MsgBox "Adding " & strBurnPath & " folder to the disc...", vbInformation, "Data Archiving"
FSI.Root.AddTree strBurnPath, False
' Create an image from the file system image object
Set Result = FSI.CreateResultImage()
Set stream = Result.ImageStream
' Write stream to disc using the specified recorder
MsgBox "Writing content to the disc...", vbInformation, "Data Archiving"
DataWriter.Write (stream)
MsgBox "Completed writing Archive data to disk ", vbInformation, "Data Archiving"
ExitHere:
Exit Sub
'Error handling block
TestCDWrite_Error:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, "TestCode.TestCDWrite"
End Select
Resume ExitHere
Application.DisplayAlerts = True
'End Error handling block
End Sub