Solved

How can I make VBA WinINet file-download code work in 64-bit Excel

Posted on 2013-11-10
14
2,851 Views
Last Modified: 2013-11-19
I'm unable to make the embedded VBA-based WinINet file-download code work in Excel 2013 64-bit. I've already modified the declarations for 64 bit, but files still don't download. This code has been working reliably in 32-bit Excel (for PC) for years.

Option Private Module

Option Compare Text


' For downloading a file from the internet
' Experts Exchange 9/23/09  egl1044

' This download code doesn't currently work in 64 bit Office (need to fix the API calls)  11/17/10
' Bring this up when working with a  VBA consultant

Private Const INTERNET_FLAG_NO_CACHE_WRITE = &H4000000
Private Const INTERNET_FLAG_RELOAD = &H80000000
Private Const INTERNET_FLAG_RESYNCHRONIZE = &H800&
Private Const WININET_API_FLAG_SYNC = &H4&
Private Const INVALID_HANDLE_VALUE = (-1)
Private Const CREATE_ALWAYS = &H2&
Private Const GENERIC_WRITE = &H40000000


' No VBA Inspector Update (no match)
#If Win64 Then
  ' crashes Excel if LongLong not used for more than first parameter
  Private Declare PtrSafe Function CreateFileW Lib "kernel32" (ByVal lpFileName As LongLong, ByVal dwDesiredAccess As LongLong, ByVal dwShareMode As LongLong, ByVal lpSecurityAttributes As LongLong, ByVal dwCreationDisposition As LongLong, ByVal dwFlagsAndAttributes As LongLong, ByVal hTemplateFile As LongLong) As Long
#Else
  Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
#End If

#If Win64 Then
  Private Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongLong, lpBuffer As LongLong, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As LongLong) As LongLong  ' Inspector: lpBuffer As Any, lpOverlapped As OVERLAPPED
#Else
  Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
#End If

#If Win64 Then
  Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongLong) As LongLong
#Else
  Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
#End If

' No VBA Inspector Update (Ignored)
#If Win64 Then
  Private Declare PtrSafe Function InternetOpenW Lib "wininet" (ByVal lpszAgent As LongLong, ByVal dwAccessType As LongLong, ByVal lpszProxyName As LongLong, ByVal lpszProxyBypass As LongLong, ByVal dwFlags As LongLong) As Long
#Else
  Private Declare Function InternetOpenW Lib "wininet" (ByVal lpszAgent As Long, ByVal dwAccessType As Long, ByVal lpszProxyName As Long, ByVal lpszProxyBypass As Long, ByVal dwFlags As Long) As Long
#End If

' No VBA Inspector Update (Ignored)
#If Win64 Then
  Private Declare PtrSafe Function InternetOpenUrlW Lib "wininet" (ByVal hInternet As LongLong, ByVal lpszUrl As LongLong, ByVal lpszHeaders As LongLong, ByVal dwHeadersLength As LongLong, ByVal dwFlags As LongLong, ByVal dwContext As LongLong) As Long
#Else
  Private Declare Function InternetOpenUrlW Lib "wininet" (ByVal hInternet As Long, ByVal lpszUrl As Long, ByVal lpszHeaders As Long, ByVal dwHeadersLength As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
#End If

' No VBA Inspector Update (Ignored)
#If Win64 Then
  Private Declare PtrSafe Function InternetReadFile Lib "wininet" (ByVal hFile As LongLong, ByVal lpBuffer As LongLong, ByVal dwNumberOfBytesToRead As Long, lpdwNumberOfBytesRead As Long) As LongLong
#Else
  Private Declare Function InternetReadFile Lib "wininet" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal dwNumberOfBytesToRead As Long, lpdwNumberOfBytesRead As Long) As Long
#End If

' No VBA Inspector Update (Ignored)
#If Win64 Then
  Private Declare PtrSafe Function InternetCloseHandle Lib "wininet" (ByVal hInternet As LongLong) As LongLong
#Else
  Private Declare Function InternetCloseHandle Lib "wininet" (ByVal hInternet As Long) As Long
#End If

' No VBA Inspector Update (Ignored)
#If Win64 Then
  Private Declare PtrSafe Function InternetQueryDataAvailable Lib "wininet" (ByVal hFile As LongLong, lpdwNumberOfBytesAvailable As Long, ByVal dwFlags As LongLong, ByVal dwContext As LongLong) As LongLong
#Else
  Private Declare Function InternetQueryDataAvailable Lib "wininet" (ByVal hFile As Long, lpdwNumberOfBytesAvailable As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
#End If


' *********

'For checking the internet connection
' Code from Randy Birch (VBNet)

Private Const FLAG_ICC_FORCE_CONNECTION = &H1

' No VBA Inspector Update (Ignored)
#If Win64 Then
  Private Declare PtrSafe Function InternetCheckConnection Lib "wininet.dll" Alias "InternetCheckConnectionA" (ByVal lpszUrl As String, ByVal dwFlags As Long, ByVal dwReserved As Long) As Long
#Else
  Private Declare Function InternetCheckConnection Lib "wininet.dll" Alias "InternetCheckConnectionA" (ByVal lpszUrl As String, ByVal dwFlags As Long, ByVal dwReserved As Long) As Long
#End If

' *********

   
' Open Web Doc
#If Win64 Then
  Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As LongLong, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongLong
#Else
  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
#End If



' ********************************************************************
' ********************************************************************
' ********************************************************************
' ********************************************************************




' Download File
' Download File
' Download File
' Download File
' Download File



Public Function DownloadFile_PC(ByVal FileLink As String, ByVal FullFileName As String, Timeout As Integer, FileSize As Single) As Integer
  
' MB Experts Exchange question answered 9/23/09 by egl1044

Dim Buffer() As Byte ' raw buffer.
Dim hOpen As Long
Dim hConn As Long
Dim hFile As Long
Dim dwBytes As Long
Dim dwWrittenBytes As Long
Dim dwReadBytes As Long

Dim FileName As String
Dim StartTimer As Double, DownloadedBytes As Single, y As Integer, IterationGap


StartTimer = Timer



' For progress form updating

' 5,500 bytes per iteration on MB's Lenovo 1/28/10

' should have 50 time-out checks & progress box updates per file, which must be based on the expected overall number of iterations per file
If FileSize <> 0 Then
  IterationGap = Int(FileSize / 5500 / 50)
Else
  IterationGap = 50  ' not necessarily 50 checks -- only if the file size is 5,500 bytes * 50
End If


'  _____

DoEvents

' Create and overwrite the file with write access.
hFile = CreateFileW(StrPtr("\\?\" & FullFileName), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)
  
' If this fails check rights and permissions...etc
If hFile = INVALID_HANDLE_VALUE Then
  'Debug.Print Err.LastDllError
  Exit Function
End If

DoEvents

' Open connection force sync download.
hOpen = InternetOpenW(0, 1, 0, 0, WININET_API_FLAG_SYNC)

DoEvents

' Establish connection to URL.
hConn = InternetOpenUrlW(hOpen, StrPtr(FileLink), 0, 0, _
INTERNET_FLAG_NO_CACHE_WRITE Or _
INTERNET_FLAG_RELOAD Or _
INTERNET_FLAG_RESYNCHRONIZE, 0)

DoEvents

Do

  If InternetQueryDataAvailable(hConn, dwBytes, 0, 0) Then
    ' Allocate the amount that is immediatley available.
      ReDim Buffer(dwBytes) As Byte
  Else
    ' Allocate 1KB chunk if the amount available fails.
      dwBytes = 1024
      ReDim Buffer(dwBytes) As Byte
  End If
    
  If InternetReadFile(hConn, VarPtr(Buffer(0)), dwBytes, dwReadBytes) Then
    ' At this point we can write the bytes to the file.
    WriteFile hFile, VarPtr(Buffer(0)), dwReadBytes, dwWrittenBytes, 0
  Else
    Exit Do
  End If

  
  ' Progress update & check for timeout
  ' Added by MB
  
  DownloadedBytes = DownloadedBytes + dwBytes
  y = y + 1
  If y / IterationGap = Int(y / IterationGap) Then  ' only check every 25 iterations -- presumably slowed down otherwise
    DoEvents
    If Timer - StartTimer > Timeout Then DownloadFile_PC = 2: Exit Do
    
    If FileSize <> 0 Then Call UpdateProgressBox(, DownloadedBytes / FileSize)
    
  End If
 

Loop Until dwReadBytes = 0

DoEvents

' perform cleanup.
InternetCloseHandle hConn

DoEvents

InternetCloseHandle hOpen

DoEvents

CloseHandle hFile

DoEvents
  
' free memory
Erase Buffer

DoEvents
'  _____

If DownloadFile_PC = 0 Then DownloadFile_PC = 1


End Function

Open in new window

0
Comment
Question by:bishop3000
  • 8
  • 5
14 Comments
 
LVL 18

Expert Comment

by:Steven Harris
ID: 39637720
Have you tried the following with the original working code?

To write code that can port between both 32-bit and 64-bit versions of Office you only need to use the new LongPtr type alias instead of Long or LongLong for all pointers and handle values.

Although I see you have been working through some of this already, this MSDN Overview may be of some help.  64-Bit Visual Basic for Applications Overview
0
 

Author Comment

by:bishop3000
ID: 39639247
Thanks, I did refer to that MSDN Overview and I've tried declaring the local variables as LongLong. Still no luck. I don't get a run-time error -- it just doesn't download.
0
 
LVL 26

Expert Comment

by:MacroShadow
ID: 39639426
Not a full answer but....

1. I wouldn't recommend conditional compilation for each declaration on it's own, put them all in one group. i.e.
#If VBA7 And Win64 Then     ' 64 bit Excel
    ' All 64-bit declarations
#Else     ' 32 bit Excel
    ' All 32-bit declarations
#End If

Open in new window


2. Not every long is a LongLong, most likely the ones that have to be changed will be LongPtr.

3. I don't know about the wininet declarations (I can't find any documentation) but here are some changes to the other api calls for 64 bit.
Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As LongPtr
    bInheritHandle As Long
End Type
Declare PtrSafe Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr
Type OVERLAPPED
        Internal As LongPtr
        InternalHigh As LongPtr
        offset As Long
        OffsetHigh As Long
        hEvent As LongPtr
End Type
Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long
Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long

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

Open in new window

0
 

Author Comment

by:bishop3000
ID: 39639437
Thanks so much, I'll try that out when I'm back at my 64 bit machine and will let you know how it goes.
0
 

Author Comment

by:bishop3000
ID: 39640689
My attempt to resolve tonight was a total fail.

I updated the code per MacroShadow's suggestions (attached). Also tried many variations of different declarations. Still no luck downloading a file in 64-bit Excel VBA.

Thanks for helping me clean up the code. Any further suggestions appreciated!

' For downloading a file from the internet
' Experts Exchange 9/23/09  egl1044

' This download code doesn't currently work in 64 bit Office (need to fix the API calls)  11/17/10
' Bring this up when working with a  VBA consultant

Private Const INTERNET_FLAG_NO_CACHE_WRITE = &H4000000
Private Const INTERNET_FLAG_RELOAD = &H80000000
Private Const INTERNET_FLAG_RESYNCHRONIZE = &H800&
Private Const WININET_API_FLAG_SYNC = &H4&
Private Const INVALID_HANDLE_VALUE = (-1)
Private Const CREATE_ALWAYS = &H2&
Private Const GENERIC_WRITE = &H40000000


#If VBA7 And Win64 Then
  ' Following 1: No VBA Inspector Update (Ignored)
  Private Declare PtrSafe Function CreateFileW Lib "kernel32" (ByVal lpFileName As LongPtr, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As LongPtr, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr   ' crashes Excel if LongLong not used for more than first parameter
  Private Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, lpBuffer As LongPtr, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As LongPtr, lpOverlapped As LongPtr) As LongPtr  ' Inspector: lpBuffer As Any, lpOverlapped As OVERLAPPED
  Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As LongPtr
  
  ' Following 5: No VBA Inspector Update (Ignored)
  Private Declare PtrSafe Function InternetOpenW Lib "wininet" (ByVal lpszAgent As LongPtr, ByVal dwAccessType As Long, ByVal lpszProxyName As LongPtr, ByVal lpszProxyBypass As LongPtr, ByVal dwFlags As Long) As LongPtr
  Private Declare PtrSafe Function InternetOpenUrlW Lib "wininet" (ByVal hInternet As LongPtr, ByVal lpszUrl As LongPtr, ByVal lpszHeaders As LongPtr, ByVal dwHeadersLength As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As LongPtr
  Private Declare PtrSafe Function InternetReadFile Lib "wininet" (ByVal hFile As LongPtr, ByVal lpBuffer As LongPtr, ByVal dwNumberOfBytesToRead As Long, lpdwNumberOfBytesRead As LongPtr) As LongPtr
  Private Declare PtrSafe Function InternetCloseHandle Lib "wininet" (ByVal hInternet As LongPtr) As LongPtr
  Private Declare PtrSafe Function InternetQueryDataAvailable Lib "wininet" (ByVal hFile As LongPtr, lpdwNumberOfBytesAvailable As LongPtr, ByVal dwFlags As Long, ByVal dwContext As Long) As LongPtr


#Else
  Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
  Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
  Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
  Private Declare Function InternetOpenW Lib "wininet" (ByVal lpszAgent As Long, ByVal dwAccessType As Long, ByVal lpszProxyName As Long, ByVal lpszProxyBypass As Long, ByVal dwFlags As Long) As Long
  Private Declare Function InternetOpenUrlW Lib "wininet" (ByVal hInternet As Long, ByVal lpszUrl As Long, ByVal lpszHeaders As Long, ByVal dwHeadersLength As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
  Private Declare Function InternetReadFile Lib "wininet" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal dwNumberOfBytesToRead As Long, lpdwNumberOfBytesRead As Long) As Long
  Private Declare Function InternetCloseHandle Lib "wininet" (ByVal hInternet As Long) As Long
  Private Declare Function InternetQueryDataAvailable Lib "wininet" (ByVal hFile As Long, lpdwNumberOfBytesAvailable As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
#End If





' ********************************************************************
' ********************************************************************
' ********************************************************************
' ********************************************************************




' Download File
' Download File
' Download File
' Download File
' Download File



Public Function DownloadFile_PC(ByVal FileLink As String, ByVal FullFileName As String) As Integer
  
' MB Experts Exchange question answered 9/23/09 by egl1044

Dim Buffer() As Byte ' raw buffer.


#If VBA7 And Win64 Then
  Dim hOpen As LongPtr
  Dim hConn As LongPtr
  Dim hFile As LongPtr
#Else
  Dim hOpen As Long
  Dim hConn As Long
  Dim hFile As Long
#End If
  
Dim dwBytes As Long
Dim dwWrittenBytes As Long
Dim dwReadBytes As Long




'  _____

DoEvents

' Create and overwrite the file with write access.
hFile = CreateFileW(StrPtr("\\?\" & FullFileName), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)
  
' If this fails check rights and permissions...etc
If hFile = INVALID_HANDLE_VALUE Then
  'Debug.Print Err.LastDllError
  Exit Function
End If

DoEvents

' Open connection force sync download.
hOpen = InternetOpenW(0, 1, 0, 0, WININET_API_FLAG_SYNC)

DoEvents

' Establish connection to URL.
hConn = InternetOpenUrlW(hOpen, StrPtr(FileLink), 0, 0, _
INTERNET_FLAG_NO_CACHE_WRITE Or _
INTERNET_FLAG_RELOAD Or _
INTERNET_FLAG_RESYNCHRONIZE, 0)

DoEvents

Do

  If InternetQueryDataAvailable(hConn, dwBytes, 0, 0) Then
    ' Allocate the amount that is immediatley available.
      ReDim Buffer(dwBytes) As Byte
  Else
    ' Allocate 1KB chunk if the amount available fails.
      dwBytes = 1024
      ReDim Buffer(dwBytes) As Byte
  End If
    
  If InternetReadFile(hConn, VarPtr(Buffer(0)), dwBytes, dwReadBytes) Then
    ' At this point we can write the bytes to the file.
    WriteFile hFile, VarPtr(Buffer(0)), dwReadBytes, dwWrittenBytes, 0
  Else
    Exit Do
  End If

Loop Until dwReadBytes = 0

DoEvents

' perform cleanup.
InternetCloseHandle hConn

DoEvents

InternetCloseHandle hOpen

DoEvents

CloseHandle hFile

DoEvents
  
' free memory
Erase Buffer

DoEvents
'  _____

If DownloadFile_PC = 0 Then DownloadFile_PC = 1


End Function

Open in new window

0
 
LVL 26

Expert Comment

by:MacroShadow
ID: 39640872
A. Please post a working file, not only the code.
B. Do you get an error, or it just doesn't work?
0
 

Author Comment

by:bishop3000
ID: 39642741
Here's a working file.
I don't get an error -- it just doesn't work.
Thanks for your help.
Download-File-to-Desktop.xlsm
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 26

Expert Comment

by:MacroShadow
ID: 39654182
Sorry for the delay. Try this instead of the code you're using now:

Option Explicit

#If VBA7 And Win64 Then
    Private Declare PtrSafe Function URLDownloadToFile _
            Lib "urlmon.dll" Alias "URLDownloadToFileA" _
            (ByVal pCaller As LongPtr, _
             ByVal szURL As String, _
             ByVal szFileName As String, _
             ByVal dwReserve As Long, _
             ByRef lpfnCB As LongPtr) _
             As Long
#Else
    Private Declare Function URLDownloadToFile _
            Lib "urlmon" Alias "URLDownloadToFileA" _
            (ByVal pCaller As Long, _
             ByVal szURL As String, _
             ByVal szFileName As String, _
             ByVal dwReserved As Long, _
             ByVal lpfnCB As Long) As Long
#End If

Sub DownloadFileFromWeb()
On Error GoTo err_1

    Dim strUrl As String
    Dim strSavePath As String
    Dim returnValue As Long
    
    strUrl = Range("WebLink").Value
    strSavePath = GetDesktop_PC & "ongrid-tool-user-manual.pdf"
    returnValue = URLDownloadToFile(0, strUrl, strSavePath, 0, 0)

Err_Exit:
    Exit Sub
    
err_1:
    MsgBox Err.Description
    Resume

End Sub

Open in new window

0
 

Author Comment

by:bishop3000
ID: 39655013
Thanks for your continued effort. Your code works great on my machine running Excel 2010 32-bit. Unfortunately it immediately crashes Excel 2013 64-bit on the other machine.
0
 
LVL 26

Expert Comment

by:MacroShadow
ID: 39655570
Surprisingly enough, that's good news. This should work.

Option Explicit

#If VBA7 Then
    Private Declare PtrSafe Function URLDownloadToFile _
            Lib "urlmon" Alias "URLDownloadToFileA" _
            (ByVal pCaller As Long, _
            ByVal szURL As String, _
            ByVal szFileName As String, _
            ByVal dwReserved As Long, _
            ByVal lpfnCB As Long) As Long
#Else
    Private Declare Function URLDownloadToFile _
            Lib "urlmon" Alias "URLDownloadToFileA" _
            (ByVal pCaller As Long, _
             ByVal szURL As String, _
             ByVal szFileName As String, _
             ByVal dwReserved As Long, _
             ByVal lpfnCB As Long) As Long
#End If

Sub Demo()
    Call DownloadFileFromWeb(Range("WebLink").Value, GetDesktop_PC & "ongrid-tool-user-manual.pdf")
End Sub

Public Function DownloadFileFromWeb(strUrl As String, strSavePath As String) As Long
On Error GoTo err_1

' Returns 0 if success, error code if not.
' Error codes:
' -2146697210 "file not found".
' -2146697211 "domain not found".
' -2147467260 "transfer aborted". 

    DownloadFileFromWeb = URLDownloadToFile(0, strUrl, strSavePath, 0, 0)

Err_Exit:
    Exit Function
    
err_1:
    MsgBox Err.Description
    Resume

End Function

Open in new window

0
 

Author Comment

by:bishop3000
ID: 39656858
Thanks MacroShadow, I'll try it out when I'm back at my 64-bit computer tonight and will let you know.
0
 
LVL 26

Accepted Solution

by:
MacroShadow earned 500 total points
ID: 39656884
OK. It should work, I tested it on a 64-bit OS and 64-bit Office.
0
 

Author Comment

by:bishop3000
ID: 39659515
That works! Thanks so much! Our 64-bit Excel users will be very happy.
0
 

Author Closing Comment

by:bishop3000
ID: 39659518
Very grateful for MacroShadow's help!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Our Group Policy work started with Small Business Server in 2000. Microsoft gave us an excellent OU and GPO model in subsequent SBS editions that utilized WMI filters, OU linking, and VBS scripts. These are some of experiences plus our spending a lo…
In this article, I will show you HOW TO: Install VMware Tools for Windows on a VMware Windows virtual machine on a VMware vSphere Hypervisor 6.5 (ESXi 6.5) Host Server, using the VMware Host Client. The virtual machine has Windows Server 2016 instal…
The viewer will learn how to successfully create a multiboot device using the SARDU utility on Windows 7. Start the SARDU utility: Change the image directory to wherever you store your ISOs, this will prevent you from having 2 copies of an ISO wit…
With the advent of Windows 10, Microsoft is pushing a Get Windows 10 icon into the notification area (system tray) of qualifying computers. There are many reasons for wanting to remove this icon. This two-part Experts Exchange video Micro Tutorial s…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now