Sunday, November 27, 2016

How To capture ADO provider errors that the VBA Error object does show

Err_Execute:

   ' Notify user of any errors that result from
   ' executing the query
   If rstTemp.ActiveConnection.Errors.Count > 0 Then
      For Each Err In rstTemp.ActiveConnection.Errors
         MsgBox "Error number: " & Err.Number & vbCr & _
            Err.Description
      Next Err
   End If

   Resume Next




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Err_Execute:

   ' Notify user of any errors that result from
   ' executing the query
   If rstTemp.ActiveConnection.Errors.Count > 0 Then
      For Each Err In rstTemp.ActiveConnection.Errors
         MsgBox "Error number: " & Err.Number & vbCr & _
            Err.Description
      Next Err
   End If

   Resume Next

How to release object variables in ADO

 ' clean up
    If Not rstTitles Is Nothing Then
        If rstTitles.State = adStateOpen Then rstTitles.Close
    End If
    Set rstTitles = Nothing

    If Not Cnxn Is Nothing Then
        If Cnxn.State = adStateOpen Then Cnxn.Close
    End If
    Set Cnxn = Nothin

How to make an ADO Connection to SQL Server

Microsoft continuos updates the drivers for ADODB so depending on which version of SQL use: '

Dim Cnxn As ADODB.Connection
Open connection strCnxn = "Provider='sqloledb';Data Source='MySqlServer';" & _ "Initial Catalog='Pubs';Integrated Security='SSPI';" 
 Set Cnxn = New ADODB.Connection 
 Cnxn.Open strCnxn

Saturday, November 26, 2016

Enterprise Application setup part 1/3

App Setup Section: Overview For a professional enterprise wide application, several critical tasks need to be accomplished at application's setup. They can loosely be defined as: setup: Define system wide settings like default output folder, printer settings and other configurable setting that will be used throughout the application's life cycle display a splash screen: Display application setting like application name, major/minor version info while giving the user something pretty to look at prompt to login a user: verify that the user is actually allowed to use the application and force him/her to enter a user id and password and be authenticated by the database - either MS Access or preferable a true enterprise wide database like MS SQL Server In reality, this is an expansive topic that covers a lot of ground so there will be separate blog posts to cover how to make a splash screen and validate a user's credentials via a login screen Section: Setup Global/PUblic variables are defined in modGlobals. Generally, these should be public constants and public variabls but MS Access has a known bug that values in public variables are lost if the application goes in BREAK mode so the TempVars variables will be used instead. Variable Name Data Type Note gbApp_SetupOccurred Boolean Flag indicates if setup occurred. Used to coordinate if certain menu options are enabled/disabled gstrUserName String The login of the user. Usually a call in the Windows API TempVars(“UserAccessLevel”) Variant User Access level which is configured per application. Basic values can be Read or Read/Write or finer level of permissions Dependencies modGlobal Public Const ERR_MSG_REQUIRED_FIELD_MISSING As String = _ "Required field. Can't be blank or missing." Public Const ERR_MSG_INVALID_START_DATE As String _ = "Invalid Start Date or must be less than ending Date" Public Const ERR_MSG_BLANK_NAME As String = "Required value -must supply a name" Public Const ERR_MSG_NO_RIGHTS_TO_FUNCTION As String = "Not enough priveleges to run this command. " & _ "Please contact system administrator for more assistance" Public Const ERR_MSG_EXISTS_IN_QUEUE As String = "No need to try again because it is all ready in the queue of pending changes." '===================================================== Public Const APP_NAME As String = "ProductivityTool" 'Public APP_PATH As String 'Public APP_INPUT_PATH As String 'Public APP_OUTPUT_PATH As String 'Public Const APP_PATH As String = CurrentProject.Path 'Public Const APP_INPUT_PATH As String = AddBS(APP_PATH) & "Input" 'Public Const APP_OUTPUT_PATH As String = AddBS(APP_PATH) & "Output" Public Const APP_LOCAL_APP_PATH As String = "C:\My Documents\My App" Public Const APP_LOCAL_INPUT_PATH As String = APP_LOCAL_APP_PATH & "\" & "Input" Public Const APP_LOCAL_OUTPUT_PATH As String = APP_LOCAL_APP_PATH & "\" & "Output" Public Const COMPANY_NAME As String = "Deutsche Bank AG" 'Public gbDEBUG_MODE As Boolean Public gbApp_SetupOccurred As Boolean Public Const MASK_DATE As String = "mm/dd/yyyy" Public Const MASK_MONEY As String = "$#,##0.00;($#,##0.00)" Public Const MASK_HOLDINGS As String = "#,##0;(#,##0)" Public lngMyEmpID As Long Public gstrUserName As String 'Public gUserAccessLevel As UserRole How Public Sub StartUp() 'will rename to init globals 'will read from INI file to get path for executable Dim objCatalog As Object 'ADOX.Catalog Dim objTable As Object 'ADOX.Table Dim strAppPath As String On Error Resume Next Set objCatalog = CreateObject("ADOX.Catalog") 'Set objCatalog = New ADOX.Catalog Set objCatalog.ActiveConnection = CurrentProject.Connection 'Set objTable = New ADOX.Table Set objTable = CreateObject("ADOX.Table") objTable.Name = "DailyWork" Set objTable.ParentCatalog = objCatalog Set objTable = objCatalog.Tables("DailyWork") strAppPath = JustPathfromFileName(objTable.Properties("Jet OLEDB:Link DataSource")) Application.TempVars.Add "AppPath", strAppPath gbApp_SetupOccurred = True 'getAppPath() 'Call SetErrorFilePath(CurrentProject.Path) 'log errors here Call SetErrorFilePath(strAppPath) 'log errors here gbDEBUG_MODE = Len(Dir$(AddBS(CurrentProject.Path) & "debug.ini")) > 0 'gsREG_APP= 'APP_NAME = "CPLI App" End Sub

Thursday, November 24, 2016

Head to Head ADO vs DAO CRUD Operations



--Setup

Create table dbo.SampleInvoice
(
SampleInvoiceID int identity(1,1) not null,
AsofDate datetime null,
[Amount] float not null,
userid nvarchar(255) null,
Source nvarchar(5)
)

create proc uspSampleInvoiceAdd
(
@asofdate datetime,
@amount float=null,
@userid nvarchar(255)=null,
@Source nvarchar(5)='ADO'
)
as

set nocount on
insert into SampleInvoice
(
AsofDate,
Amount,
UserId,
Source
)
values (@asofdate,@Amount,@userid,@Source)

-- test
exec uspSampleInvoiceAdd @asofdate='20160101',@amount=1.01,@userid='ut2998',@source='SQL'

select * from dbo.sampleinvoice
 ' Notify user of any errors that result from
    ' executing the query
    If rstTitles.ActiveConnection.Errors.Count >= 0 Then
       For Each Err In rstTitles.ActiveConnection.Errors
          MsgBox "Error number: " & Err.Number & vbCr & _
             Err.Description
       Next Err
    End If
Clean up resources

 ' clean up
    If Not rstTitles Is Nothing Then
        If rstTitles.State = adStateOpen Then rstTitles.Close
    End If
    Set rstTitles = Nothing

    If Not Cnxn Is Nothing Then
        If Cnxn.State = adStateOpen Then Cnxn.Close
    End If
    Set Cnxn = Nothing

Monday, November 21, 2016

Top 10 Using an ADO recordset with a form

How to delete a row
Set rs = Me.gridPhoneNumberDetail2.Form.Recordset
        If vbYes = MsgBox("Delete " & vbCrLf & strMsg, vbYesNo + vbInformation, "Confirm Action") Then
            rs.Delete
            If Not rs.EOF() Then rs.MoveNext
        End If
 

Set rs = Nothing

How to add a record?

Dim strSQL As String

If vbYes = MsgBox("Add a new requirement", vbInformation + vbYesNo, "Confirm action") Then
    strSQL = "INSERT INTO WJDPhoneNumber(PersonInfoId) VALUES(" & _
        Forms!wjdfrmpersoninfo!PersonInfoID & ")"
        CurrentDb.Execute strSQL
    Me.Refresh
End If

How to check if there are no rows in a form's DAO recordset

Dim rs As DAO.Recordset
Set rs = Me.gridPhoneNumberDetail2.Form.Recordset
Me.cmdDeleteRequirement.Enabled = rs.RecordCount > 0

How to set the width of a column in a subform
In the Form's Open event put the following code:

Private Sub Form_Open(Cancel As Integer)
Me.gridPhoneNumberDetail2.Form.Controls("PhoneNumber").ColumnWidth = 2160
End Sub

How to make a column invisible
in the form's Open event add:

Me.gridPhoneNumberDetail2.Form.Controls("Type").ColumnHidden = True



Procedure header

'===========================================================
'Author         :William DeCastro
'Created        :08/31/2016
'Last modified  :08/31/2016 1.0 Beta
'Objective      :will Save/update talent plus rate detail to the
'               appropriate tables
'
'Arguments      :
'Sample Call    :
'Called By      :
'===========================================================

Processing files generically in VBA


Option Compare Database
Option Explicit

Private Sub cboAsofDate_AfterUpdate()
Dim ReportDate As Date

ReportDate = CDate(Me.cboAsofDate.Value)
MsgBox "Filter for report date as of " & ReportDate
End Sub

Private Sub cboTransactionID_AfterUpdate()
Dim lngPKID As Long
lngPKID = Me.cboTransactionID.Value
'MsgBox "get exposures for id " & lngPKID

Dim qdf As QueryDef
Dim db As DAO.Database
Dim strSQL As String

Set db = CurrentDb()
Set qdf = db.QueryDefs("qryODBCExposuregetAllPerTransactionId")
With qdf
    Debug.Print "Connect property=" & .Connect
    strSQL = "EXEC uspExposuregetAllPerTransactionID " & Me.cboTransactionID.Value
    .SQL = strSQL
    Debug.Print "Sql=" & strSQL
    .ReturnsRecords = True
End With

With Me.lstExposure

    .RowSource = ""
    .ColumnCount = 3
    .RowSourceType = "Table/query"
    .ColumnWidths = "1 in;2 in;2 in"
    .RowSource = "qryODBCExposuregetAllPerTransactionId"
   
    '.Requery
End With
End Sub

Private Sub cmdRefresh_Click()
Dim strMessage As String
Dim iNumberOfColumns As Integer
Dim qdf As QueryDef
Dim db As DAO.Database

If Me.cboDataAccessType = -1 Then
    MsgBox "Must select a data access type", vbInformation, "Confirm Action"
    Exit Sub
End If
    
If Me.cboDataAccessType.Value = "DAO" Then
    'MsgBox "Will refresh with DAO"
    Set db = CurrentDb()
    Set qdf = db.QueryDefs("qryStagingTableProgramFeeMainGetAll")
    With Me.lstData
        .RowSource = ""
        .RowSourceType = "Table/Query"
        .ColumnHeads = True
        .ColumnCount = qdf.Fields.Count
        .ColumnWidths = "2 in;2 in;2 in;2 in;2 in;2 ;2 in"
        .RowSource = qdf.Name
    End With
        
Else
    MsgBox "Will refresh with ADO"
End If



End Sub


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++



Option Compare Database
Option Explicit

Public Function OpeningForm(CloseForm As String, OpenForm As String)
DoCmd.Close acForm, CloseForm

DoCmd.OpenForm OpenForm, acNormal

End Function

Public Sub TestProcessFiles()
Call ProcessFiles(1)
End Sub
Public Function ProcessFiles(ByVal id As Integer)
Dim aFiles() As String
Dim objExcel As Excel.Application

Dim i As Integer
Dim bReturn As Boolean

Select Case id

    Case 1
        ReDim aFiles(0 To 0)
        'aFiles(1) = "Chase"
        aFiles(0) = "AMEX"
        
    Case Else
End Select


Set objExcel = New Excel.Application
For i = LBound(aFiles) To UBound(aFiles)
    
    bReturn = ProcessFile(objExcel, id, aFiles(i))
Next
Set objExcel = Nothing
        
ExitProc:
    ProcessFiles = bReturn
    Exit Function
    
ErrorHandler:
    
End Function

Public Function ProcessFile(objExcel As Excel.Application, id As Integer, ParamArray prm()) As Boolean
Dim bReturn As Boolean
Dim strInputPath As String
Dim strFileName As String
Const REPORT_NAME As String = "ProgramFeeAutoCalc"
Select Case id

    Case 1
       ' MsgBox "Processing " & strFileName
        strInputPath = CurrentProject.Path & "\Input\"
        strFileName = strInputPath & REPORT_NAME & "_" & prm(0) & ".xlsx"
        Debug.Print "Processing file " & strFileName & " @ " & Now()
        bReturn = ProgramFeeAccrualSave(objExcel, strFileName)
        If bReturn Then
            Debug.Print "Successfully processed file " & strFileName
        Else
            Debug.Print "Unsuccesfully processed file " & strFileName
        End If
    Case Else
End Select
    

Exit Function
    ProcessFile = bReturn
    
End Function


Private Function ProgramFeeAccrualSave(objExcel As Excel.Application, _
    ByVal strFileName As String) As Boolean

Const COL_DATE As Integer = 1
Const COL_REVENUE As Integer = 2
Const COL_COST As Integer = 3
Const COL_PROFIT As Integer = 4
'Dim objExcel As Excel.Application
Dim wb As Excel.Workbook
Dim wks As Excel.Worksheet
Dim db As DAO.Database

Dim lngStartRow As Long
Dim lngRowCount As Long
Dim bReturn As Boolean
Dim rngAsofDate As Excel.Range
Dim rngClientID As Excel.Range
Dim lngClientID As Long
Dim asofDate As Date


Dim i As Long
Dim strMessage As String

Dim qdf As DAO.QueryDef



Set db = CurrentDb()
'Set objExcel = New Excel.Application
With objExcel
    Set wb = .Workbooks.Open(strFileName, ReadOnly:=True)
    'Set rngClientID = wb.Names("RNG_ClientID").RefersToRange.Value
    lngClientID = wb.Names("RNG_Clientid").RefersToRange.Value

    
    Set rngAsofDate = wb.Names("RNG_AsofDate").RefersToRange
    If IsDate(rngAsofDate.Value) Then
        asofDate = CDate(rngAsofDate.Value)
    End If
    
    
    Set wks = wb.Worksheets(1)
    lngRowCount = wb.Names("RNG_RowCount").RefersToRange.Value
    lngStartRow = wb.Names("RNG_RowStart").RefersToRange.Value
    Set qdf = db.QueryDefs("qryStagingTableProgramFeeMainDeleteAll")
    qdf.Execute
    
    Set qdf = Nothing
    
    
    Set qdf = db.QueryDefs("qryStagingTableProgramFeeMainAdd")
    With qdf
        .Parameters("Asofdate") = asofDate
        .Parameters("ClientID") = lngClientID
    End With
    
    For i = lngStartRow To lngStartRow + lngRowCount - 1
    
        strMessage = "No " & i - lngStartRow - 1 & " " & "Date=" & CStr(wks.Cells(i, COL_DATE)) & " " & _
            "Profit=" & CStr(wks.Cells(i, COL_PROFIT))
        With qdf
            .Parameters("txtReportDate") = CStr(wks.Cells(i, COL_DATE).Value)
            .Parameters("txtAmount") = CStr(wks.Cells(i, COL_PROFIT).Value)
            .Parameters("RowNumber") = i - lngStartRow
            .Parameters("AddedBy") = "System"
        End With
        qdf.Execute
            
            
        Debug.Print strMessage
    Next
    
    wb.Close
End With

bReturn = True
ExitProc:
    On Error Resume Next
    ProgramFeeAccrualSave = bReturn
    Set wks = Nothing
    Set wb = Nothing
    Set objExcel = Nothing
    Set qdf = Nothing
    Set db = Nothing
    Exit Function
    
End Function

Tuesday, November 8, 2016

QueryDefs with DAO and SQL Server



http://www.databasejournal.com/features/msaccess/article.php/3407531/How-to-Execute-SQL-Stored-Procedures-from-Microsoft-Access.htm

Featured Database Articles


MS Access

Posted Sep 17, 2004

How to Execute SQL Stored Procedures from Microsoft Access

By Danny Lesandrini
The simplicity and popularity of SQL Server means that more and more developers who build applications with Microsoft Access will want to learn how to take advantage of server side processing using SQL Server Stored Procedures.  The following article will demonstrate a simple method for executing procs from Access.  In addition, we'll cover questions like these:
  • How to login to SQL Server from Access and refresh object connect properties.
  • Check for existence of stored procs and add new ones where necessary.
  • Build dynamic SQL Pass Through query with parameter values.
  • Display the results of the query output in a listbox.
The  download  for this article contains all the code from the article in both Access 97 and Access 2003 versions.  You will need access to the Pubs database on a Microsoft SQL Server, including the necessary permissions to read the sysobjects table and create stored procs.  The best way to understand the process is to step through the code in debug mode and watch as it happens, but in the mean time let's look at some of the more key code scripts.

Login to SQL Server

The first step, if your application has not already managed it, is to collect and apply the login credentials to your local DAO table and/or query objects. I wrote an article about this process about four years ago and it is still available here at Database Journal.  To read it for yourself, follow this link:       ODBC DSN-Less Connection Tutorial

In fact, that's where I started when preparing the code for this article, so if you've already read that article, this login screen will be familiar to you.  The premise is simple:  collect login parameters, test validity and relink local tables and Queries.

If you name your text boxes well, the code will be very easy to read.  You will need to test each one for existence, except for the password, which may be blank, although you should be scolded if you allow blank passwords.
   ' Check for existence of Server, Database and User Name.
 ' If missing, inform user and exit.
    If IsNull(Me!txtServer) Then
        strMsg = "Enter name of your company's Server." & _
            & "(See your database administrator)"
        MsgBox strMsg, vbInformation, "Missing Data"
        Me!txtServer.SetFocus
    ElseIf IsNull(Me!txtDatabase) Then
        strMsg = "Enter name of database. (Example: PUBS)"
        MsgBox strMsg, vbInformation, "Missing Data"
        Me!txtDatabase.SetFocus
    ElseIf IsNull(Me!txtUID) Then
        strMsg = "Enter user login.  (Example: sa)" = ""
        MsgBox strMsg, vbInformation, "Missing Data"
        Me!txtDatabase.SetFocus
    Else
        strServer   = Me!txtServer
        strDatabase = Me!txtDatabase
        strUID      = Me!txtUID
        ' Password may be NULL, so provide for that possibility
        strPWD      = Nz(Me!txtPWD, "")
        
        ' Prepare connection string
        strConnect = "ODBC;DRIVER={SQL Server}" _
                & ";SERVER=" & strServer _
                & ";DATABASE=" & strDatabase _
                & ";UID=" & strUID _
                & ";PWD=" & strPWD & ";"
    End If
As you can see from the screen shot, the code also allows you to read connection information from an ini file.  While I will not take the time to list the code for that here, it is included in the download.  One might suggest that a DSN be used in place of dynamic parameters, but I have found that it is more clumsy to set up user desktops with a new DSN than it is to simply allow them to enter login credentials from the application and save them for subsequent logins.  That is my preference, so I will not cover DSNs in this article.

Make Sure Your Procs Exist

The sample application (shown below) leverages four existing stored procedures from the Pubs database, and two new ones that I created.  The metadata for these procs is stored in a local Access database, including the script to create each of them.  The next step in our process is to test for their existence and create them if they are missing.
  Private Sub CheckForStoredProcs()
    On Error Resume Next
    
    Dim qdf As dao.QueryDef
    Dim dbs As dao.Database
    Dim rst As dao.Recordset
    Dim sSQL As String
    
    ' Open a recordset of the stored procs to be used, and tested for.
    Set dbs = CurrentDb
    sSQL = "select ProcObjectName, ProcText from tblSQLProcList"
    Set rst = dbs.OpenRecordset(sSQL, dbOpenSnapshot)
    
    ' Create a querydef object and set its CONNECT property.
    Set qdf = dbs.QueryDefs("qryCheckProcs")
    qdf.Connect = strConnect
    qdf.ReturnsRecords = True
    
    ' Loop through the list, check for existance and create if needed.
    Do Until rst.EOF
        sSQL = "select count(*) as ProcExists from sysobjects " & _
               "where Name='" & rst!ProcObjectName & "'"
        qdf.SQL = sSQL
        If DLookup("[ProcExists]", "[qryCheckProcs]") = 0 Then
            ' (ProcText contains the script to create the stored proc.)
            qdf.SQL = rst!ProcText
            qdf.ReturnsRecords = False
            qdf.Execute
        End If
        rst.MoveNext
    Loop
    
    Err.Clear
    
    Set rst = Nothing
    Set qdf = Nothing
    Set dbs = Nothing
    
    End Sub
The key part in the above script is the  QueryDef.ReturnRecords  property, which must be set to TRUE when selecting records and FALSE when executing a script to create and/or alter database objects.  By the way, these procs are created automatically when you successfully login to SQL Server so they will run without error when selected in the Demo application.

Prepare and Execute Parameterized Stored Procs

The above screen shot illustrates the context sensitive nature of the criteria collection process.  Not all procs take the same parameters.  The one selected, df_Orders, requires a date range while df_Employee takes an employee name.  The table that stores the list of procs and their scripts also exposes attributes that identify which criteria options to enable.  As you click through the list, criteria collection boxes enable and disable themselves accordingly.

The code for building the SQL necessary to execute the procedures with the correct parameter values is not especially reusable, but the principal is simple and extensible.  It looks like this and the output of this script is displayed just above the listbox containing the query results. (See screen shot above.)
  Set dbs = CurrentDb
    Set qdf = dbs.QueryDefs("qryCurrentProc")
    sSQL = "exec " & lstProcs.Column(1)
    qdf.SQL = sSQL
    
    If txtPercent.Enabled Then sSQL = sSQL & " @percentage=" & txtPercent
    If txtLoLimit.Enabled Then sSQL = sSQL & " @LoLimit=" & txtLoLimit & ", "
    If txtHiLimit.Enabled Then sSQL = sSQL & " @HiLimit=" & txtHiLimit & ", "
    If txtType.Enabled Then sSQL = sSQL & " @Type='" & txtType & "'"
    If txtEmployee.Enabled Then sSQL = sSQL & " @Employee='" & txtEmployee & "'"
    If txtStart.Enabled Then sSQL = sSQL & " @Start='" & txtStart & "', @End='" & txtEnd & "'"
    
    Me.lblQuery.Caption = sSQL
    qdf.SQL = sSQL
The effect of this code is to swap out the SQL text property of the SQL Pass Through query that will be used to retrieve data.  The final step is to load the query into the listbox.  Just to make sure, the code assigns our connect string to the query's connect property.  Next, the listbox RowSource property is set to our newly updated query object and is requeried.
      qdf.Connect = strConnect
      Me.lstResults.RowSource = "qryCurrentProc"
      Me.lstResults.Requery
In addition to exposing the SQL text property of the query on the Demo application main form, there is a button that will open the actual query, along with its properties window, where you can examine all the properties exposed for a SQL Pass Through query.  Below you can see that for our ListBox query, the Return Records property is TRUE and our SQL Server login credentials are displayed in the ODBC Connect String property.

There are a number of subtleties that are not described above, like trapping for missing login parameters and moving back and forth between the login screen and the main form.  The  download  has the complete code listings and while it is nearly complete, you will likely discover some quirkiness to it.  Please overlook the minor errors and take it for what it is, a tutorial.
Also, as a final caveat I would like to admit that there other ways to accomplish the same feat, including the use of Access Data Projects (ADPs).  I have not expanded on these alternates here because I prefer the above method.  In fact, I am currently considering converting a client's ADP back to a traditional MDB and implementing the above process for data access to SQL Stored Procs.  I suppose that will give me a benchmark to test the performance difference between the access methods.  If I find that the ADP performs better, I will repent in dust and ashes and print a retraction.
      CurrentDB.QueryDefs("qryCurrentProc").SQL = "df_orders '6/15/1992', '9/15/1994'"
Sweet, huh? By assuming that our Access query has had its CONNECT property set, we just reduced the last code script to a single line.  This is easy to call for combobox sources, listboxes and even Access reports.  That is really all you need to get your Access applications to play nice with SQL Server stored procedures.  Happy computing!
» See All Articles by Columnist Danny J. Lesandrini

 

Sunday, November 6, 2016

Check whether an Excel File is Open on a Network

This function is useful if you want to see if someone else on a network has the file open

Private Declare Function lOpen Lib "kernel32" Alias "_lopen" (ByVal lpPathName As String, ByVal iReadWrite As Long) As Long
Private Declare Function lClose Lib "kernel32" Alias "_lclose" (ByVal hFile As Long) As Long

private const OF_SHARE_EXCLUSIVE=&H10

Private Function IsFileAlreadyOpen(FileName As String) As Boolean
    Dim hFile As Long
    Dim lastErr As Long
    hFile = -1
    lastErr = 0
    'hFile = lOpen(FileName, &H10)
hFile = lOpen(FileName, OF_SHARE_EXCLUSIVE)
    If hFile = -1 Then
        lastErr = Err.LastDllError
    Else
        lClose (hFile)
    End If
    sFileAlreadyOpen = (hFile = -1) And (lastErr = 32)
End Function
Private Sub Form_Load()
    MsgBox IsFileAlreadyOpen("c:\autoexec.bat")
End Sub


Private Sub CheckFileOpen()
if IsFileAlreadyOpen("C:\XYZ Corp.xlsx") then
MsgBox "File is open"
else
MsgBox "File is not open?


Saturday, November 5, 2016

Inform the use will doing a long running process in MS Access

 DoCmd.Hourglass True
    lngStartTime = GetTickCount()
    Call SysCmd(acSysCmdInitMeter, "Downloading files ...", Me.lvHistory.ListItems.Count)
    For Each objli In Me.lvHistory.ListItems
       
       
                Call CreateDailyWorkWB5(objli.SubItems(DailyWorkDetail.ClientID), _
                    objli.SubItems(DailyWorkDetail.ClientName), _
                    COB_Date, _
                    intVersionNo, _
                    intPriorVersionNo:=getPriorVersionNo())
              
                iCounter = iCounter + 1
                Call SysCmd(acSysCmdUpdateMeter, iCounter)
               
          
    Next
    lngEndTime = GetTickCount()
    lngElapsedTime = (lngEndTime - lngStartTime) * 0.001
    MsgBox "Just exported " & Format(iCounter, "##,##0") & " record(s) in " & _

        Format(lngElapsedTime, "##,##0") & " second(s) ", vbInformation, "Results"

Useful WinAPI calls


Private Declare Function ShellExecute Lib "shell32.dll" Alias _
   "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation _
   As String, ByVal lpFile As String, ByVal lpParameters _
   As String, ByVal lpDirectory As String, ByVal nShowCmd _
   As Long) As Long

Public Declare Function GetTickCount Lib "kernel32" () As Long

Private Declare Function GetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Private Declare Function GetComputerName _
Lib "kernel32" Alias "GetComputerNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long

Function getWindowsUserId() As String
' Returns the network login name.
Dim lngLen As Long, lngX As Long
Dim strUserName As String
strUserName = String$(254, 0)
lngLen = 255
lngX = GetUserName(strUserName, lngLen)
If lngX <> 0 Then
    getWindowsUserId = Left$(strUserName, lngLen - 1)
Else
    getWindowsUserId = "Unknown"
End If

End Function


Public Function GetWorkstationId() As String
' Retrieve the name of the computer.
Const acbcMaxComputerName = 15
Dim strBuffer As String
Dim lngLen As Long
strBuffer = Space(acbcMaxComputerName + 1)
lngLen = Len(strBuffer)
If CBool(GetComputerName(strBuffer, lngLen)) Then
    GetWorkstationId = Left$(strBuffer, lngLen)
Else
    GetWorkstationId = ""
End If
End Function

Public Function OpenPDFFile(ByVal strFileName) As Boolean
Dim lngErr As Long
'Dim objShell As Object

'objShell.ShellExecute
Const SW_SHOWNORMAL = 1
lngErr = ShellExecute(0, "OPEN", strFileName, vbNullString, vbNullString, SW_SHOWNORMAL)

OpenPDFFile = lngErr > 32
End Function

Useful WinAPI calls


Private Declare Function ShellExecute Lib "shell32.dll" Alias _
   "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation _
   As String, ByVal lpFile As String, ByVal lpParameters _
   As String, ByVal lpDirectory As String, ByVal nShowCmd _
   As Long) As Long

Public Declare Function GetTickCount Lib "kernel32" () As Long

Private Declare Function GetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Private Declare Function GetComputerName _
Lib "kernel32" Alias "GetComputerNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long

Function getWindowsUserId() As String
' Returns the network login name.
Dim lngLen As Long, lngX As Long
Dim strUserName As String
strUserName = String$(254, 0)
lngLen = 255
lngX = GetUserName(strUserName, lngLen)
If lngX <> 0 Then
    getWindowsUserId = Left$(strUserName, lngLen - 1)
Else
    getWindowsUserId = "Unknown"
End If

End Function


Public Function GetWorkstationId() As String
' Retrieve the name of the computer.
Const acbcMaxComputerName = 15
Dim strBuffer As String
Dim lngLen As Long
strBuffer = Space(acbcMaxComputerName + 1)
lngLen = Len(strBuffer)
If CBool(GetComputerName(strBuffer, lngLen)) Then
    GetWorkstationId = Left$(strBuffer, lngLen)
Else
    GetWorkstationId = ""
End If
End Function

Public Function OpenPDFFile(ByVal strFileName) As Boolean
Dim lngErr As Long
'Dim objShell As Object

'objShell.ShellExecute
Const SW_SHOWNORMAL = 1
lngErr = ShellExecute(0, "OPEN", strFileName, vbNullString, vbNullString, SW_SHOWNORMAL)

OpenPDFFile = lngErr > 32
End Function