Tools to use with Excel

Tools to use with Excel

When MSFT release a beta of an upcoming version of Excel (like the present one for Excel 2007) many developers & users would like to test it but don’t have access to softwares like vmWare (which I use) and Virtual PC (which other may use). One option is to use Altiris Software Virtualization Solution (SVS), which create virtualized layers that can be used to test softwares with. Two versions exist, one free for strictly personal use and one for commercial use. It require Windows 2000 SP-4 and later. It’s strongly recommended to take part of and carefully read the documentation of the software.

My favourite tool to create screenshots with is SnagiT. However, this is a commercial software and therefore may not be available for everyone. So when You are testing the beta of Excel 2007 and get some weird errors on the screen You would like to report to MSFT then one option is to use Screenshot Captor which is a free tool. It’s highly recommended to read the online help.

Speaking about Excel 2007, don’t even think to run it with a screen resolution of 800×600. The best resolution would be 1280 x 1024 or higher due to the excellent UI.

Kind regards,
Dennis

Commercial use of SQL Server 2005 Express Edition?

Hi all,

It seems that SQL Server 2005 Express Edition now can be used for commercial purposes. The following link to a recent post SQL Server Express EULA at MSDN Forums seems to confirm it and apparently it’s applicable from SP1 and forward.

With all the respect for MDBs (so called ‘Access-databases’) but this major change in the EULA will make it very interesting to replace present MDBs with SQL Server 2005 EE. What’s Your opinion about it?

Startpage: SQL Server 2005 Express Edition

Kind regards,
Dennis

Excel & PDFCreator Take II

Hi all,

Ale recently posted in a comment in Excel & PDFCreator where he informed about another free utility, pdftk tool and below is an example on how we can control it via VBA:

Option Explicit
‘ AleV 20060516

‘ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
‘ API CALLS: Wait for a Process to Terminate
‘ http://www.thescarms.com/vbasic/wait.asp
‘ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFF
 ‘Wait forever
Const WAIT_OBJECT_0 = 0
 ‘The state of the specified object is signaled
Const WAIT_TIMEOUT = &H102
‘The time-out interval elapsed & the object’s state
‘is nonsignaled.

Private Declare Function OpenProcess Lib “kernel32” (ByVal dwDesiredAccess As Long, _
            ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long

Private Declare Function WaitForSingleObject Lib “kernel32” (ByVal hHandle As Long, _
            ByVal dwMilliseconds As Long) As Long

Private Declare Function CloseHandle Lib “kernel32” (ByVal hObject As Long) As Long

Sub mergePdf(PdfDir As String, outdir As String)
    ‘ PdfDir: where the single pdf files are saved
   ‘ outdir: output folder
   
   
    Dim cmdApp As String
       
    Dim lPid As Long, lHnd As Long, lRet As Long
    cmdApp = “C:inpdftkpdftk.exe “ & PdfDir & “*.pdf cat output “ & _
    outdir & “” & Format(Now(), “yyyymmddhhmmss”) & “_MERGED_REPORT.pdf”
    lPid = Shell(cmdApp, vbNormalFocus)
    If lPid <> 0 Then
        ‘Get a handle to the shelled process.
       lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
        ‘If successful, wait for the application to end and close the handle.
       If lHnd <> 0 Then
                lRet = WaitForSingleObject(lHnd, INFINITE)
                CloseHandle (lHnd)
        End If
End If

End Sub

Sub ExampleMergePDF()
    With ThisWorkbook.Worksheets(“cp”)
        mergePdf .Range(“PDFdir”).Value, .Range(“outdir”).Value
    End With
    MsgBox “done!”
End Sub

I hope that there soon will be a solution to allow code examples to be posted in the comments without being corrupted.

Anyway, thanks for the input :)

Kind regards,
Dennis

Add and remove shortcuts in the Open & Save As dialogs

Add and remove shortcuts in the Open & Save As dialogs

Creating and removing customized shortcuts can either be done manually or via code. When we make any change(s) it will affect all Office programs.

Manually
If we want to do it manually we need to open the Regeditor and locate the following key in Windows registry:

HKEY_CURRENT_USERSoftwareMicrosoftOfficeVersionnumberCommonOpen FindPlacesUserDefinedPlaces

The ‘Versionnumber’ refers to 9.0, 10.0, 11.0 and later.

– Under this key we create a new subkey and name it (for instance Daily Dose)
– For the new subkey we add two string values:
‘Name’ and with the value for the name to be showed in the dialogs (for instance Daily Dose)
‘Path’ and with the value of the pathway to be available in the dialogs (for instance c:Daily Dose)

The following image shows the settings in the registry:


(The screenshot is from my Swedish Windows XP)

Another important subkey is ‘Places’ which contain the string value ‘ItemSize’. It control if the shortcuts will be showed as compressed (value 0) or not (value 1). If we have many shortcuts it can be suitable to ‘compact’ them in the dialogs. The ‘ItemSize’ can be located at the following place in Windows registry:

HKEY_CURRENT_USERSoftwareMicrosoftOfficeVersionnumberCommonOpen FindPlaces

Via code
The below solutions use the RegObj.dll and for more information about Regobj please see Add-ins – Working with Windows registry

Option Explicit
Option Private Module

‘A reference to the Registration Manipulation Classes must be set.

Dim m_regRootKey As RegKey
Dim m_regMainKey As RegKey
Dim m_stSubRoot As String
Dim m_stSubPlace As String

Sub Add_ShortCut_Office()
If Add_ShortCut(“11.0”, “XL-Dennis”, “My storage”, “c:XL-Dennis”, 0) Then
    MsgBox “The shortcut has successfully been added to the list.”, vbInformation
Else
    MsgBox “The shortcut already exist in Windows Registry.”, vbInformation
End If
End Sub

Sub Remove_ShortCut_Office()
If Remove_ShortCut(“11.0”, “XL-Dennis”, 1) Then
    MsgBox “The shortcut has successfully been removed.”, vbInformation
Else
    MsgBox “The shortcut does not exist in Windows Registry.”, vbInformation
End If
End Sub

Function Add_ShortCut(ByVal stXLVersion, _
                                                   ByVal stMainKey As String, _
                                                   ByVal stName As String, _
                                                   ByVal stPath As String, _
                                                   ByVal lnSize As Long) As Boolean

On Error GoTo Error_Handling

‘Registry path to set the size of the shortcuts in the dialogs.
m_stSubPlace = “SoftwareMicrosoftOffice” & stXLVersion & _
                                  “CommonOpen FindPlaces”

‘Registry path to add user defined places.
m_stSubRoot = “SoftwareMicrosoftOffice” & stXLVersion & _
                                 “CommonOpen FindPlacesUserDefinedPlaces”

‘Set the rootkey.
Set m_regRootKey = RegKeyFromHKey(HKEY_CURRENT_USER)

‘Parse the subkey.
Set m_regMainKey = m_regRootKey.ParseKeyName(m_stSubRoot)

With m_regMainKey
    .SubKeys.Add stMainKey ‘Create the subkey.
   With .SubKeys(stMainKey)
        ‘Add the shortcuts which are string values.
       .Values.Add “Name”, stName, RegValueType.rvString
        .Values.Add “Path”, stPath, RegValueType.rvString
    End With
End With

‘Parse the subkey.
Set m_regMainKey = m_regRootKey.ParseKeyName(m_stSubPlace)

‘It seems that there only exist two workable values, 0 and 1
‘where 0 represent the compacted status and 1 the standard.
If lnSize > 1 Then
    lnSize = 1
ElseIf lnSize < 0 Then
    lnSize = 0
End If

If m_regMainKey.Values(“ItemSize”).Value <> lnSize Then
    m_regMainKey.Values(“ItemSize”).Value = lnSize
End If

Add_ShortCut = True

ExitHere:
‘Release objects from memory.
Set m_regRootKey = Nothing
Set m_regMainKey = Nothing
Exit Function

Error_Handling:
    ‘Error 35004 indicates that the shortcut entry already exist.
   If Err.Number = 35004 Then Add_ShortCut = False
    Resume ExitHere
End Function

Function Remove_ShortCut(ByVal stXLVersion, _
                                                           ByVal stMainKey As String, _
                                                           ByVal lnSize As Long) As Boolean

On Error GoTo Error_Handling

m_stSubPlace = “SoftwareMicrosoftOffice” & stXLVersion & _
                                  “CommonOpen FindPlaces”

m_stSubRoot = “SoftwareMicrosoftOffice” & stXLVersion & _
                                 “CommonOpen FindPlacesUserDefinedPlaces”

Set m_regRootKey = RegKeyFromHKey(HKEY_CURRENT_USER)

Set m_regMainKey = m_regRootKey.ParseKeyName(m_stSubRoot)

m_regMainKey.SubKeys.Remove stMainKey

Set m_regMainKey = m_regRootKey.ParseKeyName(m_stSubPlace)

If lnSize > 1 Then
    lnSize = 1
ElseIf lnSize < 0 Then
    lnSize = 0
End If

If m_regMainKey.Values(“ItemSize”).Value <> lnSize Then
    m_regMainKey.Values(“ItemSize”).Value = lnSize
End If

Remove_ShortCut = True
   
ExitHere:
Set m_regRootKey = Nothing
Set m_regMainKey = Nothing
Exit Function

Error_Handling:
    ‘Error 35006 indicates that the shortcut entry does not exist.
   If Err.Number = 35006 Then Remove_ShortCut = False
    Resume ExitHere
End Function

The following picture shows the Open Dialog when we have added a shortcut (via the above code) and also have compressed the list:

Shortcuts

For privacy I have removed all info in the dialog

The above is applicable for Excel 2000 and later.

Kind regards,
Dennis

Important: Whenever You are working with the Windows registry make sure You first make a backup of the registry.

Excel & PDFCreator

Excel & PDFCreator

Creating PDF files from Excel is not always an easy task, especially when we would like to automate it via VBA. Another aspect is that not everyone has access to Adobe Acrobat to create PDF files with.

Ken Puls (a regular poster at VBAX and JMT) has recently published several Excel examples how to create PDF Files with the free tool PDFCreator:

Examples: Excel & PDFCreator (You need to scroll down on the page)

To download the free PDFCreator use this link: PDFCreator

It’s great to see that we have alternative options to create PDF files with. At present I’ve only made some simple tests. So far I’ve noticed that we need to check if there exist any data in the source sheet(s) before calling the PDFCreator.

Does anyone else have experience with it?

Full credit to Ken for publishes good examples on how to use PDFCreator :)

Kind regards,
Dennis

Edit note:
The following post refer to the input about the pdftk tool from Ale: Excel & PDFCreator Take II

Add-ins – Excel Loader – A standalone utility to start Excel and load selected add-ins

Add-ins – Excel Loader – A standalone utility to start Excel and load selected add-ins

This is the last post about add-ins and Windows registry. You can find the previously posts at the following URLs:
Add-ins – Where does Windows store the information?
Add-ins – Working with Windows registry

Before setting the focus on the tool I would like to explicit thanks the following kind people who have helped me out in various ways:

My good friends in the UK:
– Richie Sill (testing the tool and also correct my poor English (not yet done) )
– Will Riley (testing the tool)
Friends in the Netherlands:
– Jan Karel Pieterse (basic testings of the tool with Excel 2007)
– Jurgen Volkerink (aka KeepItCool) for some interesting input and knowledge about COM add-ins and especially about the COM add-ins for the VB-editor.

Any eventually remaining bug(s) or weird behavior(s) of Excel Loader can only be booked on my account.

Excel Loader
Below is a screenshots that shows the main dialog of the tool. Initially the tool read the present settings for the available add-ins when an Excel version has been selected. In the first column (Name) the file name of the add-ins (XLA/XLL) and the ProgID for the COM add-ins are viewed. Additional information about pathways, type of add-in and their status are showed in the second column.

ExcelLoader

The steps to work with the utility are the following:

# 1 Start Excel Loader.
# 2 Choose version of Excel (only installed versions can be used and so called ghost versions, i e removed previously versions, are ignored).
# 3 Choose if Excel will start with a new workbook or with an existing workbook.
# 4 Choose which add-ins should be loaded (checked) or not (unchecked) when Excel is launched.
# 5 Launch Excel by clicking on the Load Excel button.

Settings
In order to locate the add-ins that are shipped with Microsoft Excel you must configure which main folders Excel Loader should look into. This include also any personal add-ins stored in these main folders.

This is done in the following dialog:

ExcelLoader1

The default settings in the dialog refer to the English version and if you use an English version then click on the Save settings button and close the dialog. If you use another language version you need to change them before saving the settings. The settings are stored in the Windows registry.

Based on my experience with several language versions of Excel it seems that Solver and XLStart are valid main folders for most language versions of Excel. If I’m wrong please let me know.

The installation package is available here for download (my English homepage):
Excel Loader

Excel Loader was originally developed with classic VB (which is the available version for download) but has been ported to Delphi 2006 as I try hard to learn C#.

For those of You who have no interest of the Excel Loader but would like to explore the web help system can access the following URL:
Help System by RoboHelp Office

Speaking about controling add-ins, Charles Williams has developed a nice utility for handling add-ins in a network that may be of interest: Add-in Loader

Finally, if You have any questions about the utility or find a bug please send me an e-mail (the address can be located in the help system) about it or make a comment in this blog.

Kind regards,
Dennis

Excel conference in London (July 19/20th)

Hi all,

For the very first time I have decided to attend an international Excel conference. The conference will be in London, UK, by the end of July 2006.

The older I get the more I prefer diversity and I have realized that most subjects can be viewed in many different ways, i e there exist usually not one ‘truth’. This is the professional driving force to me to attend and which also explain why I nowadays see learning as a never ending process. However, I will not attend to any class just the conference itself.

It will also be great to see some persons in the real life who I have contact with via forums and lists for several years as well as new faces and names.

I’m pleased to see that the following persons will be among the speakers:
– Andy Pope
– Bob Philips
– Charles Williams
– Simon Murphy

For more information about the conference please see:
2006 UK Excel Conference

After the conference I will make a post about my impressions and conclusions.

Kind regards,
Dennis

Add-ins – Working with Windows registry

Add-ins – Working with the registry in Windows
In this second post about Add-ins and loading Excel via automation I’ll discuss how we can manipulate the Windows Registry without using Windows API.

To take part of the first part please see the following post:
Add-ins – Where does Windows store the information?

Regobj.dll
The Regobj.dll is an ActiveX Server that gives us an object model and a structure which reduce the complexity when working with the registry. A Word document is shipped together with the DLL file which gives a general description about the RegObj.dll. It’s available for download at the following place: RegObj

Locate the path to Excel’s main folders
For many applications it’s common to create flexible solutions in that we need to consider the existence of several versions of Excel. In addition, we cannot assume that Excel is always installed in the default location. So when we raise the question how to locate the paths to Excel main folders we are forced to consider these conditions. The goal of this process is to retrieve the names of XLAs/XLLs that are shipped with Excel and their respectively pathways.

I consider the following folders as the main folders for XLAs /XLLs shipped with Excel (in US/English version of Excel):
-Library
-Analysis
-SOLVER
-XLSTART

The below code is created with classic VB and in order to locate the main folder for Excel (based on which version we want to locate) we need to do a two steps approach. First locate the CLSID in the HKEY_CLASSES_ROOT and then retrieve the pathway from the subkey “LocalServer32” in the same section of the registry.

Private Sub ButtonLoad_Click()
Dim stXLversion As String

stXLversion = Me.Combo1.Text

If Locate_XLAs_XLLs_Take_One(stXLversion) = False Then
    MsgBox “The selected version is not available on the computer.”, vbInformation
    Exit Sub
Else
   ‘Do other stuff
End If
End Sub

‘A reference to the Registration Manipulation Classes must be set.
‘A reference to the Microsoft Scripting Runtime must be set.

Function Locate_XLAs_XLLs_Take_One(ByVal stVersion As String) As Boolean
‘Notable: The string variable stVersion refers to “9”, “10”, “11” etc.
Dim stSubRoot As String, stCLSID As String, stExcel As String
Dim stMainPath As String, stLibrary As String, stAnalysis As String
Dim stFoldersArr(0 To 3) As String
Dim stSolver As String, stXLStart As String
Dim objRootKey As RegKey, objStartKey As RegKey
Dim fsoObj As Scripting.FileSystemObject
Dim fsoFolder As Scripting.Folder
Dim fsoFile As Scripting.File
Dim iCounter As Integer

On Error GoTo Error_Handling

‘Instantiate the FileSystemObject.
Set fsoObj = New FileSystemObject

‘Define the subkey.
stSubRoot = “Excel.Application.” & stVersion & “CLSID”

‘Define the rootkey.
Set objRootKey = RegKeyFromHKey(HKEY_CLASSES_ROOT)

‘Parse the subkey.
Set objStartKey = objRootKey.ParseKeyName(stSubRoot)

‘Retrieve the CLSID for the wanted Excel version.
stCLSID = objStartKey.Value

‘Redefine the subkey.
stSubRoot = “CLSID” & stCLSID & “LocalServer32”

‘Parse the subkey
Set objStartKey = objRootKey.ParseKeyName(stSubRoot)

‘Clean up the obtained value.
stExcel = Replace$(objStartKey.Value, “/automation”, “”)

‘Extract the main path in which Excel.exe is located in.
stMainPath = Mid$(stExcel, 1, InStrRev(stExcel, “”, , vbBinaryCompare))

stLibrary = stMainPath & “Library”
stAnalysis = stLibrary & “Analysis”
stSolver = stLibrary & “SOLVER”
stXLStart = stMainPath & “XLSTART”

‘Populate the array with the pathways to the main folders.
stFoldersArr(0) = stLibrary
stFoldersArr(1) = stAnalysis
stFoldersArr(2) = stSolver
stFoldersArr(3) = stXLStart

‘Iterate through the collection of folders and print
‘name and pathway for the located XLAs/XLLs in the immediate window.
For iCounter = 0 To 3
    If fsoObj.FolderExists(stFoldersArr(iCounter)) Then
        Set fsoFolder = fsoObj.GetFolder(stFoldersArr(iCounter))
        For Each fsoFile In fsoFolder.Files
            If LCase$(fsoFile.Name) Like “*xla” Or LCase$(fsoFile.Name) Like “*.xll” Then
                Debug.Print fsoFile.Name & “;” & fsoFile.Path
            End If
        Next fsoFile
    End If
Next iCounter

Locate_XLAs_XLLs_Take_One = True

‘Release objects from memory.
ExitHere:
Set fsoFile = Nothing
Set fsoFolder = Nothing
Set fsoObj = Nothing
Set objStartKey = Nothing
Set objRootKey = Nothing
Exit Function

Error_Handling:
    ‘Error 35006 indicates that the choosen version is not available.
   If Err.Number = 35006 Then Locate_XLAs_XLLs_Take_One = False
    Resume ExitHere
End Function

An alternative approach to search for files in the folders is to identify each add-in’s CLSID and retrieve the pathway in HKEY_CLASSES_ROOT. However, the downside is how we should do to solve it for custom’s add-ins.

Locate the present user’s path
Below is a snippet code to locate the present user’s path and to retrieve the XLAs/XLLs names and pathways in the user’s folder (if any add-ins exists at all):

‘This API call is necessary to get the present username.
Declare Function GetUserName Lib “advapi32.dll” Alias “GetUserNameA” _
                                    (ByVal lpBuffer As String, nSize As Long) As Long
               
‘….
Dim Buffer As String * 100
Dim BuffLen As Long

BuffLen = 100
GetUserName Buffer, BuffLen
stUserName = Left(Buffer, BuffLen – 1)

stUserFolder = “C:Documents and Settings” & stUserName & _
                          “Application DataMicrosoftAddIns”

If fsoObj.FolderExists(stUserFolder) Then
    Set fsoFolder = fsoObj.GetFolder(stUserFolder)
    For Each fsoFile In fsoFolder.Files
       If LCase$(fsoFile.Name) Like “*xla” Or _
          LCase$(fsoFile.Name) Like “*.xll” Then
           Debug.Print fsoFile.Name & “;” & fsoFile.Path
        End If
    Next
End If

Change load behavior of COM add-ins
COM Add-ins load behavior can be controlled by either changing the LoadBehavior subkey in the registry setting or by using the Connect property of the COM add-ins as the following snippet code shows:

xlApp.COMAddIns(“ProgID”).Connect = True

However, for COM add-ins that target the VB-editor the load behavior seems to be only controlled via the registry setting as the following sample shows:

Option Explicit
Const stSubKey As String = “SoftwareMicrosoftVBAVBE6.0Addins”

Sub Write_To_Registry()
Dim objRootKey As RegKey
Dim objStartKey As RegKey
Dim objCOMKey As RegKey
Dim objCOM As RegValue

Set objRootKey = RegKeyFromHKey(HKEY_CURRENT_USER)
Set objStartKey = objRootKey.ParseKeyName(stSubKey)
Set objCOMKey = objStartKey.ParseKeyName(“IndenterVBA.Connect”)
Set objCOM = objCOMKey.Values(“LoadBehavior”)

‘Change the load behavior to connected | bootload.
objCOM.Value = 3

Set objCOMKey = Nothing
Set objStartKey = Nothing
Set objRootKey = Nothing

End Sub

RegObj.dll create a less complex code writing then with Windows API however the use of the DLL as well as the use of Microsoft Scripting Runtime can cause an overhead in the application that may or may not be a problem.

For more information about Windows API and additional information about the subject please see the following articles:

How To use the Registry API to Save and Retrieve Setting
How to Determine the Path for an Office Application
How to build an Office 2000 COM add-in in Visual Basic
INFO: Excel COM Add-ins and Automation Add-ins
How to run multiple versions of Excel on the same computer

In the third and final post I’ll present a standalone utility that lets us choose which add-ins to be loaded or not when loading Excel through automation.

Kind regards,
Dennis