Wednesday, December 08, 2004

LogMeIn - Remote Access Software

LogMeIn - Remote Access Software and Remote Control Software

I LOVE free stuff. As an MCT, I've had a free 1 year trial to GoToMyPC - a really cool and easy to use remote access software. I've had it installed on my home computer and can easily access it from ANY java enabled web browser. Unfortunately, my year is almost up. So, I've been looking for reasonable alternatives (GoToMyPC is 20 bucks a month!!!). I think I've found it ...

LogMeIn took me all of 5 minutes to install and get configured ... and it seems to work very well - especially for free. If you have the need to access your home computer from work or vice versa you should definitely check this out!

Tuesday, December 07, 2004

Threat profiliing Microsoft SQL Server

Threat profiliing Microsoft SQL Server

This document is an excellent overview of the security vulnerabilities with SQL Server. This is a must read for any dba out there that is trying to decide which authentication mode to use.

Personally, I rarely recommend using SQL Server Authentication. I've seen developer's tell their dba they MUST use SQL Server Authentication for programming - only because all the examples you see in books and online use "sa" with no password. I am shocked at the number of systems I have seen setup this way. Don't fall into this trap. Take the extra time to learn how to use Windows Authentication via code. This article should open your eyes to the real threats.

Tuesday, November 30, 2004

Pro SQL Server Reporting Services


Just got this new book on Reporting Services ... VERY good book. If you are just starting out or need help with some good examples, I highly recommend this book.

Stored procedure to find all instances of a field

As a report writer, database administrator, developer or user, it may be useful to know which table a field exists in. Many third party vendors don't supply a data schema, making it difficult to query and build reports. This stored procedure is a simple method of searching through all the table in the current database for a field that you specify.

While you certainly cannot assume that because two tables have the same field that they are related, this will certainly be at least one tool you can use to help find those relationships.

CREATE PROCEDURE dbo.sp_FieldInfo
(
@Column_Name nvarchar(384) = NULL
)
AS
SELECT Object_Name(id) as 'Table Name',
rtrim(Name) as 'Field Name'
FROM syscolumns
WHERE name like @Column_Name
GO

Then to call this proc:
sp_fieldinfo employeeid

Wednesday, November 24, 2004

Email attachment limits

What a pain it is when you want to email someone a large file only to find out Hotmail, Gmail, Yahoo, or any of the other numerous email providers don't support large attachments - most only allow up to 10mb. 10MB?? With today's focus on media (pictures, movies, songs, etc.) - how can I email a bunch of pictures in one big zip file?

Yousendit has started a service which will allow you to email large attachments to somebody - up to 1 GIG!! THAT'S more like it! Using the yousendit website, you upload your file, enter the email addresses you want it sent to, a link is sent to them via email, they click on the link to download the file. Your file is stored for seven days, then deleted. VERY COOL!

Tuesday, November 16, 2004

Office Developer Center: VBA Language References

Office Developer Center: VBA Language References

Microsoft has recently published the language references for all of the Office 2003 applications. You can view them online or download them.

If you are a VBA programmer, you should download these useful references.

Blogging on Visio

Blogging on Visio

Just found another great blog with very useful tips and techniques using Microsoft Visio. For some strange reason, Visio seems to have very little documentation and there aren't many Visio books available. If you see other Visio sites or have any books to recommend, please post in the comments - thanks!

Thursday, November 04, 2004

Microsoft Photo Story 3 for Windows: make show-n-tell cool again

Microsoft Photo Story 3 for Windows: make show-n-tell cool again

If you are into photo editing or you share your photos with friends and family - you gotta check this out! Microsoft Photo Story 3 - it's free!!!

Bring life into your favorite memories with Photo Story 3 for Windows by adding motion, effects, music, and more to your digital photos. Easily retouch your images with a single click and add slick-looking titles, or add dramatic pans and zooms that give your creations a professional finish, create a soundtrack - even record narration. Then enjoy the show. Start sharing your stories today!

Retrieve current username from windows using VBA

Ever needed to retrieve username of the person currently logged into Windows? Using VBA in any of the Office products, the following code will return the current username. Great for implementing your own security or auditing.

' Makes sure all variables are dimensioned in each subroutine.
Option Explicit

' Access the GetUserNameA function in advapi32.dll and
' call the function GetUserName.
Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long

' Main routine to Dimension variables, retrieve user name
' and display answer.
Sub Get_User_Name()

' Dimension variables
Dim lpBuff As String * 25
Dim ret As Long, UserName As String

' Get the user name minus any trailing spaces found in the name.
ret = GetUserName(lpBuff, 25)
UserName = Left(lpBuff, InStr(lpBuff, Chr(0)) - 1)

' Display the User Name
MsgBox UserName
End Sub

Wednesday, November 03, 2004

Library of Free Data Models

Library of Free Data Models

Reading the news groups today, I came across this little gem of a website. If you are just starting out with database design or need help coming up with a data model, this website gives some EXCELLENT examples of well designed databases.

Tuesday, October 26, 2004

Remind yourself to send attachments with Outlook

Ever forget to send an attachment to someone? The following code will search your outgoing message text for the word "attach." You can add as many words as you want. The code needs to go in the ThisOutlookSession module in Outlook VBA; make sure macro security is not set to High.

Private Sub Application_ItemSend(ByVal Item as Object, Cancel as Boolean)
If Instr(1, Item.Body, "attach", vbTextCompare) > 0 Then
If Item.Attachments.Count = 0 Then
MsgBox "You forgot the attachment."
Cancel = True
End If
End If
End Sub

For more examples of VBA using Outlook, check out Sue Mosher's site OutlookCode.

Microsoft Access Performance Considerations

While Access is certainly NOT an enterprise solution for databases, it can certainly provide small to medium size businesses with a very valid solution for their database needs. It's very common to read discussions about how Access cannot handle a multi-user environment or is too slow to use across the network. Most of the time, I find there are major design flaws with the databases these people are using. For most developer, there a few simple configurations and code tricks that can be used to attain reasonable performance from Access.

First, it is VERY possible to create a successful client/server application using linked tables for up to 20 concurrent users. But there are lots of details you must fix to be successful. To get good performance, it's all about keeping the "wire" cool -- that is, making sure you minimize the amount of data you ask JET to fetch and the number of threads you have open to the file server.

One of the most insidious "wire" eaters in Access 2000 and later is the silly Subdatasheet feature. If you leave SubdatasheetName set to [Auto], Access opens an extra thread AND fetches the rows for any recordset built on the table. You'll see a dramatic improvement in performance if you go to all the tables in the data file on the server and set this property for each table to [None].

You must also design your application to minimize the data fetched to the client machine. It is NOT true that JET on the client always does a full table scan. If you apply a filter on an indexed field, JET first fetches the index blocks and then sends specific requests to the file server for the data pages it needs to satisfy the request. So, it's important to both define appropriate indexes on your tables AND to NEVER request "all the tea in china" by opening a form or report unfiltered.

You should design custom "query by form" forms into your application that prompt the user to focus on the records needed for the task at hand, and the QBF code should refuse to proceed unless the user specified at least one filter value. You should also avoid any combo boxes that return more than about 200 rows. Although Access does try to optimize the combo box row source by not fetching all the rows until the user types in the box or drops it down, fetching 1000+ rows in a combo box is a performance killer. Most successful applications provide a way for the user to filter the combo first - for example, by selecting a product category that then filters the product name list. One alternative is to write code in the Change event to lookup the closest value for the user as the user types the entry they want. Single probes via DLookup are much more efficient than fetching the 1000+ row recordset.

In applications that might release the last active thread by returning to an unbound switchboard, performance can be improved by keeping one recordset open in code as long as the application is running. When you close the last bound form or report, Access releases the thread to the server - and if someone else has the data database open, it can take seconds to reopen the thread. If you keep a thread open, other processes in the application will share the open thread.

For reports, consider fetching the "unnormalized" report data to a local table and bind the report to that. Depending on how your report is designed, the report engine can end up fetching all the data from the server four or five times before it displays the result. Also, if you open a large report in Print Preview and the user pages back and forth in the result, the report engine will fetch the data several times again.

Be advised that "upsizing" to SQL Server is not a panacea. If your appication is badly designed for client/server, it won't run any better on SQL Server, and might actually run worse. You should upsize only when you need to manage more than 200 meg of data, you need true security, or you need to support more than 20 simultaneous users.

As for lookups - don't use them, at least not in table definitions. Check out my previous discussion for more information.

The Access Web - The Evils of Lookup Fields in Tables

The Access Web - The Evils of Lookup Fields in Tables

Lookup fields are a hot topic for debate, that's for sure. If you frequent Access newsgroups or discussion forums, you've probably seen at least one heated thread about whether developers should use lookup fields in their tables. Personally, I tend to agree lookup fields should NOT be used. The misunderstanding most people have regarding this stance is that they believe the functionality of lookup fields is lost. Not true.

Unless you have a *rock solid* understanding of relational theory and the detailed structure of your database, it is a very bad idea. It gets you very little - it makes your table datasheet view more human readable, at the cost of concealing the actual contents of the table, and makes sorting and searching the table more difficult; it also makes it a tiny bit easier to put combo boxes on forms instead of textboxes. But I advise people never to use this misfeature; just put the combo boxes on Forms, which is what you should be using to look at your data anyway. Table datasheets are for debugging; and as such they should display what they actually contain rather than concealing it.

You can very easily store your tables with the actual data that they contain visible, and use a Query or a combo box or other control on a Form or Report to retrieve data from the linked ("lookup", if that's what you want to call it) table. What I object to is the perverse idea that you should define a lookup *FIELD* in your main table, and use it in your table datasheet. This accomplishes absolutely nothing other than to conceal the actual contents of your table, cause confusion about the relational structure of your data, and mislead users into trying to do data entry and searching in table datasheets instead of properly doing so on Forms.

It's perfectly easy to put a Combo Box - a "lookup", if you want to call it that - on a Form. The table lookup wizard makes this the default, but at the cost of concealing the actual contents of your table; encouraging you to use table datasheets for data entry, almost never a good idea; creating a new relationship between the main table and the lookup table even if such a relationship already exists; and adding redundant indexes to your table. If you leave the tables alone, and use a Form to do your data entry, you get the best of both worlds. Use table datasheets for debugging and design ONLY, and use the Form and the rich kit of tools that the Form provides for your data entry.

For more detailed information, follow this articles link to the MVPs Access site.

Saturday, October 23, 2004

Filter a report using a form's filter

There is a relatively simple way of filtering a report by using the filter property of a form. This allows the user to filter any field on the form and then print the displayed records in a report. Now, instead of creating complex queries or multiple controls on a criteria form, you can let the users decide how to filter the report.


This form is based on the customers table from the Northwind sample database. The country field has been filtered to show only those customers located in Germany.

Now, place the following code behind the Preview Report button's On Click event:
DoCmd.OpenReport "rptCustomers", acPreview, , IIf(Me.FilterOn = True, Me.Filter, "")

Now, once the user clicks on the the Preview Report button, the report uses the filter property of the form, if a filter has been set.


Posted by Hello
This report is now filtered using the same filter used on the form.

Tuesday, October 19, 2004

Lookout email search for Microsoft Outlook

Lookout email search for Microsoft Outlook - Lookout Software

Ok, one more on the software side of things - search Outlook for all those emails, contacts, and calendar items you thought you had lost!

You can use Lookout to search your:

  • Email messages
  • Contacts, calendar, notes, tasks, etc.
  • Data from exchange, POP, IMAP, PST files, Public Folders
  • Files on your computer or other computers
  • ... your wife's purse (okay, not true)

This software was recently acquired by Microsoft and is tightly integrated with Outlook. Definitely worth checking out if you live and breath Outlook.

Google Desktop Beta

How many times have you thought it would be great to be able to search your desktop as easily as Google searching the web?

  • Find your email, files, web history and chats instantly
  • View web pages you've seen, even when you're not online
  • Search as easily as you do on Google

Google Desktop Beta

Ad Ware Removal and Detection

Lately, spam has taken a back seat to Ad Ware. What is Ad Ware and Spyware? Spyware and Adware is software made by publishers that allow them to snoop on your browsing activity, invade your privacy, and flood you with those horrible popups. If you are like most users on the internet, chances are you are probably infected with these applications. Unfortunately, most novice users don't know how to remove these pesky softwares. I've compiled a list of the software I recommend that can help you rid your computer of Ad Ware and Spyware.

While these programs are free, Ad-Aware has a professional version which does real-time monitoring - sort of like most firewall software. The free version is sufficient, but the professional version has some great tools that make it worth the upgrade price.

Ad-Aware
Spybot
HijackThis

These three are consistently the best reviewed in their categories, Spybot being the most prevalent. HijackThis uses a slightly different approach than Ad-Aware and Spybot. HijackThis scans your hard drives and registry for commonly used attack methods - not specific URLs and registry entrys like the other two. I would recommend loading all three. Several articles I have read indicate that Spybot and Ad-Aware will detect some entries the other doesn't.

More information and reviews can be obtained by reading:

CNET Spyware Reviews

Spybot Overview

Monday, October 18, 2004

What is XML?

Microsoft Office Assistance: XML for the uninitiated

XML for the uninitiated

A relatively common question in class these days - what is XML? Microsoft has provided support for it in most of their products, including, Office and SQL Server. XML really has revolutionized data distribution across the web. This article gives a very good overview in non techy terms.

Saturday, October 16, 2004

Free Virus Protection

One of the most common "excuses" I hear about not using virus protection is that it costs too much. After you buy the software, there are usually subscriptions you must pay for to keep your software up to date - preventing new viruses from attacking your computer. I have found this AVG Anti-virus to be one of the best virus protection programs available - and it's free for personal use.

What is RSS?

RSS is quickly becoming a new standard for reading news sites, blogs and other syndicated web sites. It's like a customized news reader. Click here to read an article on CNET that gives a good overview of RSS, how to use it, and what software you'll need to get started. Don't forget ... most blogs have a RSS feed. Add the link below to your RSS reader to receive the feed for this site.

http://dbageek.blogspot.com/atom.xml

I have found Pluck to be the best RSS reader. Best of all, it's FREE!

Recommended Books

Here is a list of books I recommend for database development.
Access


SQL Server and Programming

Crystal Reports
XML

Tuesday, October 05, 2004

Override the Shift key in Access

Using the startup properties in Access, the database window can be hidden when a database is open. This is usually turned on for most production databases. When the developer needs to make changes, the shift key is used when opening the database to override all startup options. This is a handy feature, but also allows other not so savy users to do the same. The AllowByPassKey property can be used to "password" protect this feature by enabling or disabling the shift key. However, because of the potential of locking yourself out of a database, Microsoft has not created this property by default.

The AllowByPassKey property is explained in detail in the VBA help file that comes with Access. However, the sample code provided in the help files does not use the fourth DDL argument when making a call to CreateProperty. This means that anyone who can open the database can programmatically reset the AllowBypassKey value.

Therefore, in order to restrict the change capabilities to only the Admins, set the fourth argument to True when calling CreateProperty. And don't lock yourself out!

Below is the code that can be used to create this property and some comments on how to use it. Check out the help file for more detail.

'*********** Code Start ***********
'This code was originally written by Michael Kaplan.
'It is not to be altered or distributed,
'except as part of an application.
'You are free to use it in any application,
'provided the copyright notice is left unchanged.
'
'Code Courtesy of
'Michael Kaplan
'
Function ChangePropertyDdl(stPropName As String, _
PropType As DAO.DataTypeEnum, vPropVal As Variant) _
As Boolean
' Uses the DDL argument to create a property
' that only Admins can change.
'
' Current CreateProperty listing in Access help
' is flawed in that anyone who can open the db
' can reset properties, such as AllowBypassKey
'
On Error GoTo ChangePropertyDdl_Err

Dim db As DAO.Database
Dim prp As DAO.Property

Const conPropNotFoundError = 3270

Set db = CurrentDb
' Assuming the current property was created without
' using the DDL argument. Delete it so we can
' recreate it properly
db.Properties.Delete stPropName
Set prp = db.CreateProperty(stPropName, _
PropType, vPropVal, True)
db.Properties.Append prp

' If we made it this far, it worked!
ChangePropertyDdl = True

ChangePropertyDdl_Exit:
Set prp = Nothing
Set db = Nothing
Exit Function

ChangePropertyDdl_Err:
If Err.Number = conPropNotFoundError Then
' We can ignore when the prop does not exist
Resume Next
End If
Resume ChangePropertyDdl_Exit
End Function

Function ChangeProperty(strPropName As String, _
varPropType As Variant, varPropValue As Variant) As Integer
' The current listing in Access help file which will
' let anyone who can open the db delete/reset any
' property created by using this function, since
' the call to CreateProperty doesn't use the DDL
' argument
'
Dim dbs As Database, prp As Property
Const conPropNotFoundError = 3270

Set dbs = CurrentDb
On Error GoTo Change_Err
dbs.Properties(strPropName) = varPropValue
ChangeProperty = True

Change_Bye:
Exit Function

Change_Err:
If Err = conPropNotFoundError Then ' Property not found.
Set prp = dbs.CreateProperty(strPropName, _
varPropType, varPropValue)
dbs.Properties.Append prp
Resume Next
Else
' Unknown error.
ChangeProperty = False
Resume Change_Bye
End If
End Function
' *********** Code End ***********

Monday, October 04, 2004

What's best for DBAs? GUI or T-SQL commands?

What's best for DBAs? GUI or T-SQL commands?

Do SQL Server DBAs really need to know the T-SQL commands for doing day to day administrative tasks? This article is one of the best explanations I've found that discusses the benefits of learning T-SQL to accomplish administrative tasks. More and more DBAs are becoming "lazy" and use the GUI that Microsoft provides, SQL Server Enterprise Manager.

Wednesday, September 29, 2004

Disable prompts when sending (Outlook) email via Access

If you have ever tried to automate the process of sending an email from within Access using VBA code, you may have seen this error message:

"A program is trying to automatically send e-mail on
your behalf. Do you want to Allow this?"

It makes you wait & then you HAVE to hit the Yes button for it to send the Email.

A SOLUTION that should work ...

Dim objOutlook As New Outlook.Application
Dim objMail As MailItem

Set objOutlook = New Outlook.Application
Set objMail = objOutlook.CreateItem(olMailItem)

EmailAddr = "xxx@AOL.com"
CopyEmailAddr = "yyy@AOL.com"
Subj = "Test subjject"
Body = "Body"
PathName = "C:\test.txt"

With objMail
.To = EmailAddr
.cc = CopyEmailAddr
.Subject = Subj
.Body = Body
.NoAging = True
.Attachments.Add PathName
.Display
End With

'****** Send the email without prompts *******
SendKeys "%{s}", True
'****************************************************

Set objMail = Nothing
Set objOutlook = Nothing

Monday, September 27, 2004

Use Microsoft Jet's ShowPlan to write more efficient queries

Use Microsoft Jet's ShowPlan to write more efficient queries

While reading some posts on the Access newsgroup, I came across this article about optimizing your Access queries. One of the most powerful features of SQL Server is being able to view the execution plan of a query. With this relatively simple registry hack, you can accomplish a very similar feature in Access, by forcing Access to export the execution plan to a text file.

Green bar reporting in Access

Many accounting style reports need help to be more readable. Ever used a ruler on a landscape report to make sure you read data from the correct row? Remember the old green bar reports from mainframes that made this easier? Well, you can accomplish the same type of layout on an Access report.

Make sure the BackStyle of each control is Transparent.

Code the Detail Format event:

If Me.Section(0).BackColor = vbWhite Then
Me.Section(0).BackColor = 12632256 ' gray
Else
Me.Section(0).BackColor = vbWhite
End If

Access your bookmarks online

MyBookmarks.com - Access your bookmarks online anytime, anywhere

I've always hated having to manage bookmarks at home, at work, on my laptop ... it gets very frustrating not having all my bookmarks on all my machines.

Now, with mybookmarks, I have a cool little icon in my system tray that I can use to quickly add any site to my bookmarks - on any machine. For example, if I'm at work and I find a cool site I want to bookmark, I add it to mybookmarks then when I get home or use my laptop, I can syncronize that new bookmark to that machine. Now I don't have to email myself links all the time.

Microsoft Announces 2006 Target Date for Windows "Longhorn"

Microsoft Announces 2006 Target Date for Broad Availability Of Windows "Longhorn" Client Operating System

Microsoft has had to re-prioritize many many times in the past several months, deciding which features will be included in the upcoming release of Windows. Longhorn (the code name for the next version of Windows) was supposed to be one of the most aggressive releases Microsoft has released; and it still might be, just not quite as feature laden as initially planned.

One of the biggest changes will be the new file system, WinFS. The current Windows file system, NTFS, is quickly becoming outdated by other operating systems (Linux, Novel, etc.). Another key feature will be the integrated mobile device support. As a huge proponent of Pocket PCs, I think this is a great move by Microsoft. One of the biggest complaints users of Pocket PCs have is the syncronization software called Activesync. I'm hoping that having the mobile support integrated into the operating system will fix many of the bugs that have plagued Activesync for years.

Only two years to go ...

Sunday, September 26, 2004

A more complete datediff function

One of the more common questions I receive in my Access classes is how to display the difference between two dates. VBA has always had the datediff function; however, this function only allows you to display the difference with one date part (year, month, or day – not all three together). So, instead of seeing the difference as 1 year 2 months and 3 days, you can choose one date part.


I highly recommend reading newsgroups for valuable information about programming (use msnews.microsoft.com if you don’t have a news server available). Microsoft MVPs (most valuable professionals) constantly post and answer questions in these groups. Douglas Steele is one of the MVPs which posts quite often and has some very useful code samples on his website.

One of the functions, posted here, lets you calculate a "precise" difference between two date/time values.

You specify how you want the difference between two date/times to be calculated by providing which of ymdhns (for years, months, days, hours, minutes and seconds) you want calculated.

For example:

?Diff2Dates("y", #06/01/1998#, #06/26/2002#)
4 years
?Diff2Dates("ymd", #06/01/1998#, #06/26/2002#)
4 years 25 days
?Diff2Dates("ymd", #06/01/1998#, #06/26/2002#, True)
4 years 0 months 25 days
?Diff2Dates("d", #06/01/1998#, #06/26/2002#)
1486 days

?Diff2Dates("h", #01/25/2002 01:23:01#, #01/26/2002 20:10:34#)
42 hours
?Diff2Dates("hns", #01/25/2002 01:23:01#, #01/26/2002 20:10:34#)
42 hours 47 minutes 33 seconds
?Diff2Dates("dhns", #01/25/2002 01:23:01#, #01/26/2002 20:10:34#)
1 day 18 hours 47 minutes 33 seconds

?Diff2Dates("ymd",#12/31/1999#,#1/1/2000#)
1 day
?Diff2Dates("ymd",#1/1/2000#,#12/31/1999#)
-1 day
?Diff2Dates("ymd",#1/1/2000#,#1/2/2000#)
1 day

'***************** Code Start **************
Public Function Diff2Dates(Interval As String, Date1 As Date, Date2 As Date, _
Optional ShowZero As Boolean = False) As Variant
'Author: © Copyright 2001 Pacific Database Pty Limited
' Graham R Seach MCP MVP gseach@pacificdb.com.au
' Phone: +61 2 9872 9594 Fax: +61 2 9872 9593
' This code is freeware. Enjoy...
' (*) Amendments suggested by Douglas J. Steele MVP
'
'Description: This function calculates the number of years,
' months, days, hours, minutes and seconds between
' two dates, as elapsed time.
'
'Inputs: Interval: Intervals to be displayed (a string)
' Date1: The lower date (see below)
' Date2: The higher date (see below)
' ShowZero: Boolean to select showing zero elements
'
'Outputs: On error: Null
' On no error: Variant containing the number of years,
' months, days, hours, minutes & seconds between
' the two dates, depending on the display interval
' selected.
' If Date1 is greater than Date2, the result will
' be a negative value.
' The function compensates for the lack of any intervals
' not listed. For example, if Interval lists "m", but
' not "y", the function adds the value of the year
' component to the month component.
' If ShowZero is True, and an output element is zero, it
' is displayed. However, if ShowZero is False or
' omitted, no zero-value elements are displayed.
' For example, with ShowZero = False, Interval = "ym",
' elements = 0 & 1 respectively, the output string
' will be "1 month" - not "0 years 1 month".

On Error GoTo Err_Diff2Dates

Dim booCalcYears As Boolean
Dim booCalcMonths As Boolean
Dim booCalcDays As Boolean
Dim booCalcHours As Boolean
Dim booCalcMinutes As Boolean
Dim booCalcSeconds As Boolean
Dim booSwapped As Boolean
Dim dtTemp As Date
Dim intCounter As Integer
Dim lngDiffYears As Long
Dim lngDiffMonths As Long
Dim lngDiffDays As Long
Dim lngDiffHours As Long
Dim lngDiffMinutes As Long
Dim lngDiffSeconds As Long
Dim varTemp As Variant

Const INTERVALS As String = "dmyhns"

'Check that Interval contains only valid characters
Interval = LCase$(Interval)
For intCounter = 1 To Len(Interval)
If InStr(1, INTERVALS, Mid$(Interval, intCounter, 1)) = 0 Then
Exit Function
End If
Next intCounter

'Check that valid dates have been entered
If Not (IsDate(Date1)) Then Exit Function
If Not (IsDate(Date2)) Then Exit Function

'If necessary, swap the dates, to ensure that
'Date1 is lower than Date2
If Date1 > Date2 Then
dtTemp = Date1
Date1 = Date2
Date2 = dtTemp
booSwapped = True
End If

Diff2Dates = Null
varTemp = Null

'What intervals are supplied
booCalcYears = (InStr(1, Interval, "y") > 0)
booCalcMonths = (InStr(1, Interval, "m") > 0)
booCalcDays = (InStr(1, Interval, "d") > 0)
booCalcHours = (InStr(1, Interval, "h") > 0)
booCalcMinutes = (InStr(1, Interval, "n") > 0)
booCalcSeconds = (InStr(1, Interval, "s") > 0)

'Get the cumulative differences
If booCalcYears Then
lngDiffYears = Abs(DateDiff("yyyy", Date1, Date2)) - _
IIf(Format$(Date1, "mmddhhnnss") <= Format$(Date2, "mmddhhnnss"), 0, 1)
Date1 = DateAdd("yyyy", lngDiffYears, Date1)
End If

If booCalcMonths Then
lngDiffMonths = Abs(DateDiff("m", Date1, Date2)) - _
IIf(Format$(Date1, "ddhhnnss") <= Format$(Date2, "ddhhnnss"), 0, 1)
Date1 = DateAdd("m", lngDiffMonths, Date1)
End If

If booCalcDays Then
lngDiffDays = Abs(DateDiff("d", Date1, Date2)) - _
IIf(Format$(Date1, "hhnnss") <= Format$(Date2, "hhnnss"), 0, 1)
Date1 = DateAdd("d", lngDiffDays, Date1)
End If

If booCalcHours Then
lngDiffHours = Abs(DateDiff("h", Date1, Date2)) - _
IIf(Format$(Date1, "nnss") <= Format$(Date2, "nnss"), 0, 1)
Date1 = DateAdd("h", lngDiffHours, Date1)
End If

If booCalcMinutes Then
lngDiffMinutes = Abs(DateDiff("n", Date1, Date2)) - _
IIf(Format$(Date1, "ss") <= Format$(Date2, "ss"), 0, 1)
Date1 = DateAdd("n", lngDiffMinutes, Date1)
End If

If booCalcSeconds Then
lngDiffSeconds = Abs(DateDiff("s", Date1, Date2))
Date1 = DateAdd("s", lngDiffSeconds, Date1)
End If

If booCalcYears And (lngDiffYears > 0 Or ShowZero) Then
varTemp = lngDiffYears & IIf(lngDiffYears <> 1, " years", " year")
End If

If booCalcMonths And (lngDiffMonths > 0 Or ShowZero) Then
If booCalcMonths Then
varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
lngDiffMonths & IIf(lngDiffMonths <> 1, " months", " month")
End If
End If

If booCalcDays And (lngDiffDays > 0 Or ShowZero) Then
If booCalcDays Then
varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
lngDiffDays & IIf(lngDiffDays <> 1, " days", " day")
End If
End If

If booCalcHours And (lngDiffHours > 0 Or ShowZero) Then
If booCalcHours Then
varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
lngDiffHours & IIf(lngDiffHours <> 1, " hours", " hour")
End If
End If

If booCalcMinutes And (lngDiffMinutes > 0 Or ShowZero) Then
If booCalcMinutes Then
varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
lngDiffMinutes & IIf(lngDiffMinutes <> 1, " minutes", " minute")
End If
End If

If booCalcSeconds And (lngDiffSeconds > 0 Or ShowZero) Then
If booCalcSeconds Then
varTemp = varTemp & IIf(IsNull(varTemp), Null, " ") & _
lngDiffSeconds & IIf(lngDiffSeconds <> 1, " seconds", " second")
End If
End If

If booSwapped Then
varTemp = "-" & varTemp
End If

Diff2Dates = Trim$(varTemp)

End_Diff2Dates:
Exit Function

Err_Diff2Dates:
Resume End_Diff2Dates

End Function
'************** Code End *****************

Check out Doug's homepage for more great samples.

Thursday, September 23, 2004

Lebans Holdings Website

I'm always looking for more resources online for examples and plugins for Access. Lebans has been one of the most invaluable resources I have found. Well known on the discussion forums for having useful addins/funtions like MouseWheel, MonthCalendar and Justification, the website is definitely worthy of your time to explore to see what they have available.

Lebans Holdings

Tuesday, September 21, 2004

Crystal Reports: Field Clipping

It seems that every new version of Crystal Reports changes how data is displayed when the field simply isn't wide enough. Until Crystal 7, the data was just clipped by the size of the field on the report. So, you could spend a pretty significant amount of time trying to figure out why the numbers on your report were wrong, only to find out that the field just needed to be made wider.

Crystal 7 introduced a new option that you could finally set to show pound signs when a number was too wide, instead of just dropping the extra digits. Unfortunately, Crystal also set this option, called "Field Clipping", off by default. Even the newer versions of Crystal, 9 and 10, still have this option set to off.

To turn off field clipping and display pound signs when a number is too wide:

File > Options
Fields Tab
Number Button (you should also do the Currency Button)
Number Tab
Customize Button
Take out the check mark in the lower left for "Field Clipping".

Only new reports will be affected. Any existing reports will still have field clipping until you change the numeric and currency fields individually. To change an individual field right-click on the field and select "Format Field". Then click the "Customize" button and take out the checkmark for "Field Clipping".

Should Microsoft be worried about Google's success?

As Goolge expands into more and more realms of the internet (gmail, froogle, google local, etc.), the author of this article seems to think Google has big plans for your desktop. A very interesting read ...

Monday, September 20, 2004

Bad Hair Day


dataDog got a haircut today. Here's a picture of him after the carnage was over. Posted by Hello

Got Gmail?

Heard of Gmail yet? It's Google's free email service which allows you to store 1 gig - yes that is 1,000,000 bytes - of email!! No more running out of space because your friend just emailed you 10 mb worth of vacation pictures you don't care to see.

The only problem is, as I posted in a previous blog, Gmail is still in beta (testing) and you can only get an account if you get "invited." I still have a few invites left that I can send out, so if you want a gmail account, email me!.

Sunday, September 19, 2004

Updated Amazon Browser Buddy Toolbar

A9

Ever wanted an easier way to find books (or any other item) at Amazon?

Amazon has finally released a new version of there award winnig search engine - complete with a browser buddy toolbar. Definitely worth checking out.

Friday, September 17, 2004

More Blogs!!

The honorable Celeste Sartor, colleague and very good friend of mine, has also recently started a blog. Definitely worth checking out! Drop her some comments, and tell her I sent you :)

Calculating the first and last day of the month

Ever needed to calculate the first and last day of the month? Here's an expression that can be used in Access:

DateSerial(Year(Now), Month(Now) + 1, 0) - Last day of month
DateSerial(Year(Now), Month(Now), 1) - First day of month

Thursday, September 16, 2004

Commonly used naming conventions

When building Access databases, it is highly recommended that you use a naming convention to standardize how you name your objects. This will make development easier for yourself and help eliminate confusion when other developers make modifications to your database. This article outlines some commonly used naming conventions.

The best way to choose good names for software objects is to employ a naming convention or standard system. Aside from better communication among programmers, the many benefits of using a naming convention include:

  • Saves time thinking up names
  • Reduces the need for comments
  • Helps you spot errors, by allowing visual consistency checks, similar to dimension checks on mathematical equations
  • Triggers early detection of design or implementation issues
  • Helps in debugging code
  • Provides an identity for the project's code and participants
  • Allows automated tool support for writing/checking code
General: Commonly used naming conventions

Wednesday, September 15, 2004

Deleting all data from an Access database

One of the questions I have had asked several times in class is how to empty a database of all existing data. You don't want to lose your tables structure, just the data. For example, you've created a new database and during the development process you have entered quite a bit of test data that needs to be removed before you release it to users. If done manually, this job can quickly become tedious. If your database has many tables, the following code will clear all the data in a hurry.


Dim ctr As Container, doc As Document, db As Database
Set db = CurrentDB()
Set ctr = db.Containiners!Tables
For Each doc in ctr.Documents
If Left$(doc.Name, 4) <> "MSys" Then 'Table is not a system table
db.Execute "DELETE [" & doc.Name & "].*" & _
"From [" & doc.Name & "];"
End If
Next doc

Recommended Sites

I have changed how I am storing my recommended sites. The goal is to share websites that I have found invaluable or simply great references. Trying to maintain a list on my blog would quickly get out of hand and be very difficult to organize. So, I have enlisted the services of Furl.

Furl is a new (still in beta) website that you can save your bookmarks to and then share them with friends. You can even subscribe to my bookmarks using their RSS feed (very cool!). If you want to know more about how to use RSS, search google or go to Furl's website for more information.

So, now when you click on Recommend Sites, you will be taken to my bookmarks page on Furl. There, you will be able to filter and view by category, popularity, rating and more. Hopefully you will all find that very useful!

Firefox browser to hit milestone

Firefox browser to hit 1.0 milestone | CNET News.com

Get Firefox!

My favorite browser is growing up! If you haven't tried Firefox yet, now's the time. The usability features (tabbed browsing, integrated search bar, extensions, skins, etc.) that Firefox introduces are what make it my browser of choice.

I have found Firefox to be more stable, faster, and easier to use than Internet Explorer. Try it out and let me know what you think!

Gmail tools and addins

Plugins and tools to make Gmail easier to use are starting to pop up on the web, click read more to see some of the most popular. Don't know what Gmail is? Click read more. Props to Rob for the original post.


* Official Gmail Notifier from Google (beta) - Downloadable Windows application that alerts you when you have new Gmail messages.
* Gmail Search Extension - Search your Gmail account from the Firefox search bar
* Gmail Tray - A search box for the Windows taskbar
* Gmail Notifier - Firefox extension, installs an icon on your toolbar that displays the amount of new messages in your inbox (previous post)
* Gmail-to - Associate all mailto: links with Gmail as opposed to Outlook
* Gmail-to Bookmarklet - Compose messages from your Gmail account from any page (previous post)
* Gmailit - Bookmarklet to send the current page you're viewing to someone through Gmail
* GMail Loader (GML) - Cross platform application forwards your existing email to Gmail
* Pop Goes the GMail - Gmail > POP3 converter
* gExodus - Graphical user interface tool allows you to import your emails into your Gmail account.
* GMail, RSS Feeds - Retrieve notifications of new mail through RSS
* Gmail Gems - Tips and Tricks to use Gmail more efficiently
* Unread Gmail - Create a label called "Unread", Gmail will automatically add all unread items to it (Via Gmail Wiki)
* GSuite - Lets you access and use Gmail from a mini-browser in the system tray
* Gmail icon generator - Create an image of your Gmail address to minimize spam exposure (Via here)

Gmail is Google's new email service. It's been a pretty hot topic on many technology news sites lately. Unfortunately, it's still in beta, which means it isn't open to the public just yet. Existing users are given "invitations" so they can give friends a gmail account. I guess that's Google's way of doing a controlled rollout of Gmail. Anyway, if you really want one and don't have one yet, shoot me an email. I may just have an invitation I can send you.

Blog separation

I've decided to go with two blogs. This blog will mainly be for technology related information while paqguy remains my personal blog.

Tuesday, January 20, 2004

Thursday, January 01, 2004

2072 - SQL Administration

Below are some useful links to supplement the course 2072 - SQL Server 2000 Administration:

SQL Server Administration Tips

SQL Server Performance

SQL Junkies

SQL Server Central

SQL Team

Migrating Access Databases to SQL Server

SQL Server Security

How to prevent the transaction log from growing unexpectedly

Track SQL Server file growth

SQL Server DTS

TSQL or GUI for SQL DBAs?

SQL Server Articles

General Microsoft SQL Server articles, tips and links:

Stored Procedure to find all instances of a field

What's best for DBA's? GUI or T-SQL commands?


Which tool should I use: Enterprise Manager or Query Analyzer?

What is XML?

How to configure Reporting Services log file reports

2073 Links

Below are some useful links to supplement the course 2073 - Programming a Microsoft SQL Server 2000 Database:

Naming Conventions

OLE DB versus ODBC data access methods

Transact SQL

T-SQL Scripts

Tracking File Growth

Cursor Performance

Query Execution Plan Analysis

SQL Server Parallel Execution Plans

10 Things You Shouldn't Do With SQL Server (Data Access Methods)

Temp tables discussed

2071 - TSQL

Below are some useful links to supplement the course 2071 - Querying SQL Server 2000 with Transact-SQL:

SQL Server Development Tips

Transact SQL

SQL Server Performance

Crystal Reports Articles

General Crystal Reports tips, tricks, and other articles

Field Clipping
Table join problems