Learn Microsoft Access Advanced Programming Techniques, Tips and Tricks.

Dynamic Dlookup in Query Column

Introduction.

If we need only a single column value from a related table to incorporate into a Microsoft Access Query then we can use a DLookup() function to bring that value into the Query Column. Normally we place that Table also into the Query's design surface, establish link between Primary Key of the main table and Foreign Key of the other table and place the required field into the query column. Here, we will examine an interesting solution to a small problem with a dlookup() function in a query column. The above method that normally we follow have some issues when implemented in the following situations, which we are going to explore.

The DLookup(“TaxRate2005”,”tblTaxRates”,”[Product Code] = ‘” & [ProductCode] & “’”) Function is used in a Query Column to pick up Sale Tax Rate from the tblTaxRates Table, for each item sold, for calculating the Sale Tax Value for the actual Sale value.  The Tax Rate will change every year during annual budgeting of the government.  The Company maintains the history of these changes and adds a new tax-rate-field with Year as Suffix to the tblTaxRates Table like: TaxRate2005, TaxRate2006, TaxRate2007 etc.  Take a look at the sample image given below:

The Query Column name is TaxRate where the Dlookup() Function is inserted, irrespective of TaxRate2005 or TaxRate2006 or TaxRate2007 is selected in the function parameter like: TaxRate:Dlookup(“TaxRate2005”,”tblName”,”Criteria”).  When we design a report we can use the report control name as TaxRate and no need to modify every time.

Check the sample Query result image given below:


Applying Different Tax Rates

Now, assume that there are Orders placed during December with the applicable Tax Rate at that time. There are Orders placed for materials immediately after the budget implementation with revised sale tax rate.  We have to prepare some invoices with previous year sale tax rates and others with current year rates.  That means the Dlookup() function will look like Dlookup(“TaxRate2005”,” “,” “) for previous year and Dlookup(“TaxRate2006”,” “, “ “) for current year.  The table name and criteria part is omitted for clarity. As you can see the first parameter of the function must be changed every time for printing previous year and current year invoices.

We cannot ask the User to go in and change the Query design.  There must be a way to define that particular parameter of the function dynamically to refer to different tax rate columns on the tblTaxRates.  The solution is very simple, design a small Form with a Text Box and a Command button and let the user type the tax rate field name  in the Text Box (or create a Combo Box if required) and click the Command Button to refresh the Query and open the Report that uses this Query as record source.  Sample image of the Query parameter Form is given below:

The Textbox name is Tax on the above form.  With that in mind our Dlookup() function in the Order Details Query column will look like as given below:

TaxRate:DLookup([Forms]![InvoiceParam]![Tax],”tblTaxRates”,”[ProdCode]= '” & [Product Code] & “'”)

In the criteria part the ProdCode field of tblTaxRate table should match with the (Product Code) field of the Products Table linked with the Order Details Table to return the tax rate value for each item on the Order Details table.


The sample SQL of the Query.

SELECT [Order Details].[Order ID],
 Products.[Product Code],
 Products.[Product Name],
 [Order Details].Quantity,
 [Order Details].[Unit Price],
 [Quantity]*[Unit Price] AS SaleValue,
 Val(DLookUp([Forms]![InvoiceParam]![Tax],"TaxRates","[ProdCode]='" & [Product Code] & "'")) AS TaxRate,
 [SaleValue]*[TaxRate] AS SaleTax,
 [SaleValue]+[SaleTax] AS TotalSaleValue
FROM Products INNER JOIN [Order Details] ON Products.ID = [Order Details].[Product ID];

The Command Button Click Event Procedure can run the following Code to open the Sales Invoice Report after refreshing the change on the Form:

Private Sub cmdRun_Click()
Me.Refresh
DoCmd.OpenReport "SalesInvoice", acViewPreview
End Sub
Technorati Tags:
Share:

Creating Watermark on MS-Access Reports

Introduction.

No matter what kind of database design you plan for your Company, reports (in text or Chart form) are the main output the external users expect from the application. The Charts can be with 2D design or can be in pretty 3D design with gradient colors which makes them more attractive to look at. In either case the information in them must be meaningful and must serve their purposes. It is like the difference between a song sung by the bathroom singer and by a professional one. The lyrics is same but the listener definitely prefer the second choice.

You can design a report in minutes. Or you can design the same report giving personal attention to each and every control on the report for their placement, control size, font size, highlighting, heading, footer, summary lines and so on. It may take several hours before you are satisfied with the idea of presenting the report to the boss, stand back and look for the sign of appreciation appearing on his face.

Talking of controls and enhancements whey can't we place a Watermark (a Company Logo or Company Name) on the Report Background to give the report a touch of class? It will not take much to do that. If you have an Image of your Company Logo (in .bmp format) with a very light gray scale color (like the image given below) you can easily implement this idea on your Report.


Incorporating Watermark on Report.

  1. Open the Report in Design View.
  2. Display the Report's Property Sheet (F4).
  3. Look for the Picture Property and click on the property to select it.
  4. Click on the Build button (. . . at the right end of the property) to browse for the Watermark image on the disk and select it.
  5. With the following three property settings of the Report you can display and print the watermark image in various ways:
    • PictureAlignment = 2 (center)
    • PictureTiling = False
    • PictureSizeMode = 3 (zoom)

When you load the Watermark picture in the background, with the above property settings, the Report Print Preview looks like the image given below:

Print the Report on Printer or convert into MS-Access Snapshot format (.snp) or into PDF.

The above manual work made easier for any Report with the VBA Code given below:


The ReportWaterMark() Function.

Public Function ReportWaterMark()
Dim rpt As Report, txtRpt As String
Dim imgPath As String

txtRprt = ""
imgPath = ""

Do While txtRpt = "" Or imgPath = ""
  If txtRpt = "" Then
   txtRpt = Nz(InputBox("Give Report Name:", "Report Water Mark"), "")
  End If
  If imgPath = "" Then
   imgPath = Nz(InputBox("Watermark Image PathName:", "Report Water Mark"), "")
  End If
Loop

DoCmd.OpenReport txtRpt, acViewDesign

Set rpt = Reports(txtRpt)
With rpt
    .Picture = imgPath
    .PictureAlignment = 2
    .PictureTiling = False
    .PictureSizeMode = 3
End With
DoCmd.Close acReport, txtRpt, acSaveYes
Set rpt = Nothing

DoCmd.OpenReport txtRpt, acViewPreview

End Function

Copy and paste the above code into a Standard VBA Module and save the code.  You can run this program from a Command Button Click Event Procedure like:


Private Sub cmdWMark_Click()
    ReportWaterMark
End Sub

When you run the main program it will prompt for the Report Name and for the Watermark Image location with image name. You must note down these information somewhere before you attempt to run the program. You need to run this program only once for a report. The image stays as the backgroud picture on the report till you run the program again to change the image.

Try the following property settings to see how they appear on the Report Print Preview:

.PictureAlignment = 0
    .PictureTiling = True
    .PictureSizeMode = 0

.PictureAlignment = 2
    .PictureTiling = False
    .PictureSizeMode = 1
Technorati Tags:
Share:

iSeries Date in Imported Data

Introduction.

If you have IBM iSeries Machine (IBM AS400) and taking raw data from there for customized report preparation in Microsoft Access then you might have noticed that the date value they provide will look like an ordinary number in mmddyyyy format (07092011) or in ddmmyyyy (09072011) or like yyyymmdd (20110709).  We cannot directly use this number as a date in a Query or anywhere else for analysis purposes. It should be converted into a real date before we can use them.

Let us try one or two conversion examples.


Example-1: mmddyyyy

x = 07092011 or x=”07092011”

y = July 09, 2011 (internal representation of the actual date number is 40733)

Conversion expression:

y = DateSerial(Right(x,4),Left(x,2),Mid(x,3,2))

OR

y = DateValue(Left(x,2) & "-" & Mid(x,3,2) & "-" & Right(x,4))

Depending on the input date format (Asian, USA or ANSI) usage order of Left(), Right() and Mid() functions in the DateSerial() or DateValue() Functions will change.  But, writing the above expressions every time when we put the data into Queries is not advisable and time consuming too.  The easiest way to overcome this is to create User-defined functions with the above expressions and call the function from the Query Column or from anywhere these date numbers are involved in calculations or comparisons etc.


The DMY_N2D() Function.

Let us create the following simple Functions that will make our life easier with these numbers on the long run.

Function: DMY_N2D(ByVal ddmmyyyy as Variant) As Date 

Converts from date number in ddmmyyyy format into a real date number.  The input number can be in Long Number format (09072011 or 9072011) or in text format “09072011”.  _N2D stands for Number to Date.  The first three characters of the function name DMY indicates the order of Day, Month & Year elements of the input date number.

Public Function DMY_N2D(ByVal ddmmyyyy As Variant) As Date
'------------------------------------------------------------------
'Converts Numbers (in ddmmyyyy format) 09072011 into a Date Number
'Author : a.p.r.pillai
'Date   : Sept. 1999
'Rights : All Rights Reserved by www.msaccesstips.com
'------------------------------------------------------------------
Dim strN2D As String

On Error GoTo DMY_N2D_Err

strN2D = Format(ddmmyyyy, "00000000") ' add 0 at the left side, if 7 digit number

DMY_N2D = DateSerial(Right(strN2D, 4), Mid(strN2D, 3, 2), Left(strN2D, 2))

DMY_N2D_Exit:
Exit Function

DMY_N2D_Err:
MsgBox Err.Description,, "DMY_N2D()"
Resume DMY_N2D_Exit
End Function

The MDY_N2D() Function.

When the input Number is in mmddyyyy format:

Public Function MDY_N2D(ByVal mmddyyyy As Variant) As Date 
'------------------------------------------------------------------ 
'Converts Numbers (in mmddyyyy format) 07092011 into a Date Number 
'Author : a.p.r.pillai 
'Date   : Sept. 1999 
'Rights : All Rights Reserved by www.msaccesstips.com 
'------------------------------------------------------------------
Dim strN2D As String 

On Error GoTo MDY_N2D_Err 

strN2D = Format(mmddyyyy, "00000000") ' add 0 at the left side, if 7 digit number

MDY_N2D = DateSerial(Right(strN2D, 4), Left(strN2D, 2), Mid(strN2D, 3, 2)) 

MDY_N2D_Exit: 
Exit Function 

MDY_N2D_Err: 
MsgBox Err.Description,, "MDY_N2D()" 
Resume MDY_N2D_Exit 
End Function

The YMD_N2D() Function.

When the date number is in yyyymmdd (ANSI) format:

Public Function YMD_N2D(ByVal yyyymmdd As Variant) As Date
'------------------------------------------------------------------
'Converts Numbers (in yyyymmdd format) 20110709 into a Date Number
'Author : a.p.r.pillai
'Date   : Sept. 1999
'Rights : All Rights Reserved by www.msaccesstips.com
'------------------------------------------------------------------
Dim strN2D As String

On Error GoTo YMD_N2D_Err

YMD_N2D = DateSerial(Left(strN2D, 4),Mid(strN2D, 5, 2),Right(strN2D, 2))

DMY_N2D_Exit:
Exit Function

YMD_N2D_Err:
MsgBox Err.Description,, "YMD_N2D()"
Resume YMD_N2D_Exit
End Function

Share:

Change Query Top Values Property with VBA-2

Continued from Last Week's Topic.

Through last week’s introduction we have seen various ways the Top Value and other properties change the SQL string of a SELECT Query.  Now we will learn how to redefine the Query for the Top Values and other property changes. 

As I have mentioned earlier three type of Queries; SELECT, APPEND and MAKE-TABLE only have the Top Values property.  SELECT and MAKE-TABLE queries have almost identical SQL string with DISTINCT, TOP nn, PERCENT clauses appearing immediately after the SELECT clause at the beginning of the SQL string. 

A sample SQL string of a make-table query is given below:

SELECT TOP 15 PERCENT SalesReportQ.* INTO chart
FROM SalesReportQ
ORDER BY SalesReportQ.Total DESC;

Unlike SELECT and MAKE-TABLE Queries APPEND Queries have the Top Values property settings inserted somewhere in the middle of the SQL string immediately after the SELECT clause. Check the sample SQL of Append Query given below:

INSERT INTO Table3 ( xID, Field1, Field2 )
SELECT DISTINCT TOP 17 PERCENT Table2.ID, Table2.Field1, Table2.Field2
FROM Table2
ORDER BY Table2.ID DESC;

Our VBA program scans through the SQL String to find the TOP Values property Clauses in the SQL String(wherever they appear), removes the existing settings and insert changes as per input from the User.

First we will create a form for the User to input Query Top Values property values and click a Command Button to redefine the SQL.

Image of a sample form is given below:

Two text boxes with the name Qry and TopVal, for Query name and for Top values parameters respectively and a checkbox with the name Unik for Unique value selection.  The Top Values text box can be set with a number or a number with a percentage symbol (like 20 or 15%).  If the Unik checkbox is set then the query suppresses duplicate records based on the selected field values in the Query.

After setting the Query property values in the above controls the user should click the Command Button to redefine the SQl of the selected query in the Query Name control.  The Command Button's name is cmdRun (with the Caption: Modify Query). When the Command Button is clicked the cmdRun_Click() Event Procedure is run (the VBA Code is given below) and validates the input values in the controls above and calls the QryTopVal() function (with parameters: query name, Top Values property value and Checkbox value) to redefine the Query based on the user inputs.


Form Module Code.

Private Sub cmdRun_Click()
Dim strQuery, strTopVal, bool As Boolean
Dim msg As String

On Error GoTo cmdRun_Click_Err

msg = ""
strQuery = Nz(Me![Qry], "")
If Len(strQuery) = 0 Then
   msg = "  *>>  Query Name not found." & vbCr
End If
strTopVal = Nz(Me![TopVal], 0)
If strTopVal = 0 Then
   msg = msg & "  *>>  Top Property Value not given."
End If
bool = Nz(Me![Unik], 0)
If Len(msg) > 0 Then
    msg = "Invalid Parameter Values:" & vbCr & vbCr & msg
    msg = msg & vbCr & vbCr & "Query not changed, Program Aborted...."
    MsgBox msg, , "cmdRun_Click()"
Else
    'Call the QryTopVal() Function to redefine the Query
    QryTopVal strQuery, strTopVal, bool
End If

cmdRun_Click_Exit:
Exit Sub

cmdRun_Click_Err:
MsgBox Err.Description, , "cmdRun_Click()"
Resume cmdRun_Click_Exit
End Sub

Copy and paste the above VBA Code into the Form Module and save the Form. Don't forget to name the Command Button as cmdRun.


The Main Function QryTopVal().

The main function QryTopVal() checks the Query Type (SELECT or APPEND or MAKE-TABLE) and if found valid then reads the SQL of the query.  Checks for the existence of Top Values and other Property settings and if they exists then removes them.  Redefines the query based on the Top Values and other property inputs from the user.

Copy and paste the following VBA Code of QryTopVal() into the Standard Module and save it:

Public Function QryTopVal(ByVal strQryName As String, _
                       ByVal TopValORPercent As String, _
                       Optional ByVal bulUnique As Boolean = False)
'--------------------------------------------------------------------
'Author : a.p.r. pillai
'Date   : Jun 2011
'Remarks: All Rights Reserved by www.msaccesstips.com
'Valid Query Types:
'  0 - SELECT
' 64 - APPEND
' 80 - MAKE TABLE
'--------------------------------------------------------------------
Dim strSQL1 As String, strSQL2 As String, strTopValue
Dim db As Database, qrydef As QueryDef, sql As String
Dim loc, qryType As Integer, locTop
Dim txt(1 To 3) As String, num
Dim J, xt, msg As String

On Error GoTo QryTopVal_Err

txt(1) = "DISTINCT"
txt(2) = "TOP"
txt(3) = "PERCENT"

Set db = CurrentDb
Set qrydef = db.QueryDefs(strQryName)
qryType = qrydef.Type

If qryType = 0 Or qryType = 64 Or qryType = 80 Then
   xt = qrydef.sql

   GoSub ParseSQL

   loc = InStr(1, TopValORPercent, "%")

   If loc > 0 Then
      TopValORPercent = Left(TopValORPercent, Len(TopValORPercent) - 1)
   End If

   If Val(TopValORPercent) = 0 Then
      sql = strSQL1 & strSQL2
   Else
      sql = strSQL1 & IIf(bulUnique, "DISTINCT ", "") & "TOP " & TopValORPercent & IIf(loc > 0, " PERCENT ", "") & strSQL2
   End If

   qrydef.sql = sql
   msg = "Query Definition of " & strQryName & vbCr & vbCr & "Changed successfully."
   MsgBox msg, , "QryTop()"
Else
   msg = strQryName & " - Invalid Query Type" & vbCr & vbCr
   msg = msg & "Valid Query Types: SELECT, APPEND and MAKE-TABLE"
   MsgBox msg, , "QryTop"
End If

QryTopVal_Exit:
Exit Function

ParseSQL:
For J = 1 To UBound(txt)
  xt = Replace(xt, txt(J), "", 1)
Next
  
  locTop = InStr(1, xt, "SELECT")
  num = Val(Mid(xt, locTop + 7))
  num = " " & Format(num) & " "
  strSQL1 = Left(xt, locTop + 7)
  xt = Right(xt, Len(xt) - (locTop + 7))
  xt = Replace(xt, num, "", 1, 1)
  strSQL2 = " " & xt
  locTop = InStr(1, strSQL2, "ORDER BY")
  If locTop = 0 Then
    MsgBox "ORDER BY Clause not found in Query.  Result may not be correct.", , "QryTopVal()"
  End If
Return

QryTopVal_Err:
MsgBox Err & " : " & Err.Description, , "QryTopVal()"
Resume QryTopVal_Exit

End Function

You may try the Code with sample Queries.

Share:

Translate



PageRank
Subscribe in a reader
Your email address:

Delivered by FeedBurner

http://clicky.com/101199826
Blog Directory Visit blogadda.com to discover Indian blogs

Search

Popular Posts

Search This Blog

Blog Archive

Powered by Blogger.

Follow by Email

Labels

Forms How Tos Functions MS-Access Security Reports msaccess forms Animations Class Module msaccess animation Utilities msaccess controls Access and Internet MS-Access Scurity MS-Access and Internet Array Queries msaccess reports External Links msaccess tips Accesstips Downloads Objects Property Event Menus and Toolbars Collection Object Controls MsaccessLinks Process Controls WithEvents Art Work msaccess How Tos Combo Boxes Graph Charts List Boxes VBA msaccessQuery Command Buttons Form Command Button Data Dictionary Object Emails and Alerts Query RaiseEvent Report Calculation Custom Wizards DOS Commands Data Type ms-access functions msaccess functions msaccess graphs msaccess reporttricks Custom Functions Item Object Reference msaccessprocess security advanced Access Security Add Field Type Fields Form Instances Key Macros Menus SubForm Top Values Variables msaccess email msaccess menus progressmeter Access2007 Auto-Number Copy Excel Expression Join Methods Microsoft Numbering System Records Recordset Security Split Table Time Difference Utility Workgroup Wrapper Classes database function ms-access msaccess wizards reference text tutorial vba code Access2003 Accounting Year Action Animation Attachment Binary Numbers Bookmarks Budgeting ChDir Color Palette Conditional Formatting Data Filtering Defining Pages Diagram Disk Dynamic Lookup Error Handler Export External Filter Formatting Groups Hexadecimal Numbers Import Labels List Logo Macro Mail Merge Main Form Memo Monitoring Octal Numbers Operating System Paste Primary-Key Product Rank Reading Remove Rich Text Sequence SetFocus Summary Tab-Page Tables Union Query User Users Water-Mark Word automatically commands hyperlinks iSeries Date iif msaccess msaccess alerts pdf files restore switch toolbar updating upload

Featured Post

Call Function From MouseMove Event Property

Introduction. This is about running a User-Defined Function (say myFunction(Parameter) ) on the Mouse Move Event Property of Text Boxes.  W...

Labels

Blog Archive

Recent Posts