vb6 trying to get old program working with excel 2013 - excel

I have this code from a program that was created to take data and export it into excel it is in vb6 and I dont know much about vb6 I started coding in vb.net could someone tell me why this isnt working with excel 2013 it opens but then closes right away and i am unsure as to why.
Sub GetExcel()
Dim MyExcel As Object ' Variable to hold reference
' to Microsoft Word.
Dim ExcelWasNotRunning As Boolean ' Flag for final release.
' Test to see if there is a copy of Microsoft Excel already running.
10 On Error Resume Next ' Defer error trapping.
' Getobject function called without the first argument returns a
' reference to an instance of the application. If the application isn't
' running, an error occurs.
20 Set MyExcel = GetObject(, "XLMAIN")
30 If Err.Number <> 0 Then ExcelWasNotRunning = True
40 Err.Clear ' Clear Err object in case error occurred.
' Check for Microsoft Excel. If Microsoft Excel is running,
' enter it into the Running Object table.
50 DetectExcel
' Set the object variable to reference the file you want to see.
60 Set MyExcel = GetObject(App.Path & "\test.xls")
' Show Microsoft Word through its Application property. Then
' show the actual window containing the file using the Windows
' collection of the MyWord object reference.
' MyExcel.Application.Visible = True
' MyExcel.document(1).Visible = True
70 MyExcel.Show , f1
'//////////////////////////////////////////////
' Do manipulations of your file here.
'//////////////////////////////////////////////
' ...
' If this copy of Microsoft Excel was not running when you
' started, close it using the Application property's Quit method.
' Note that when you try to quit Microsoft Excel, the
' title bar blinks and a message is displayed asking if you
' want to save any loaded files.
80 If ExcelWasNotRunning = True Then
90 MyExcel.Application.Quit
100 End If
110 Set MyExcel = Nothing ' Release reference to the
' application and spreadsheet.
End Sub
Sub DetectExcel()
' Procedure dectects a running Word and registers it.
Const WM_USER = 1024
Dim hwnd As Long
' If Excel is running this API call returns its handle.
10 hwnd = FindWindow("XLMAIN", 0)
20 If hwnd = 0 Then ' 0 means Word not running.
30 Exit Sub
40 Else
' Word is running so use the SendMessage API
' function to enter it in the Running Object Table.
50 SendMessage hwnd, WM_USER + 18, 0, 0
60 End If
End Sub
even if i can get some direction on how to rewrite this it would be appreciated.

It's been a long time since I've used it, so you may need to address some of the finer points... But:
First and foremost - get rid of the On Error Resume Next it masks whatever happens next.
This is not a situation where you want to have errors ignored. Capture the error, show something useful (not debug information and not details that can be used for hacking) to the user, and resume or return (after cleanup of assigned object variables to avoid memory leaks).
Then step through the code to see what errors you get.
Some of the things that may help:
Change the specification in your GetObject to be "Excel.Application" i.e.
Set MyExcel = GetObject(, "Excel.Application")
Instead of MyExcel.Show which may or may not be supported, use actual Excel objects and their methods and properties, for instance the commented MyExcel.Application.Visible = True works, while I question the MyExcel.document(1).Visible = True.
Look up the Excel object model help for details. And never hardcode the index - obtain the actual reference that you want and use it.
You can still find articles about Excel and VB6 on line. Use your search engine of choice and good luck.
Beware of those who say something is impossible - first see if it works. Some say you can's install VB6 on a 64-bit system - that is not true, but there are some issues getting it to work. Some say you can't interact with 64-bit Office from VB6, but that is not true. Maybe you can't do some things - I haven't done much with it, just enough to know it is possible to do some things.
Consider developing and testing with typed objects in VB6. It can be very helpful, but to make the application version independent, you will need to remove the object typing before final test and deployment.

Related

What about "Application" as default object in Excel VBA?

I have just written this easy macro in Excel VBA for merging a group of selected cells:
Sub Macro_Merge()
Dim Temp As String
Dim S As Variant
Temp = ""
For Each S In Selection
If Temp = "" Then
Temp = CStr(S.Value)
Else:
Temp = Temp + "," + CStr(S.Value)
End If
Next
Selection.Merge
Selection.Value = Temp
Selection.VerticalAlignment = xlTop
End Sub
This works fine, but I always see that annoying dialog box, warning me about loosing data while merging (which is exactly what I'm trying to avoid in my macro).
I can get rid of that dialog box, configuration the Application's DisplayAlerts property:
Application.DisplayAlerts = False
Selection.Merge
Selection.Value = Temp
Application.DisplayAlerts = True
This is working fine.
So, as Application is the default object, I tried to clean up my code, as follows:
DisplayAlerts = False
Selection.Merge
Selection.Value = Temp
DisplayAlerts = True
As you see, I simply omit mentioning the Application object. This is something which is allowed and I've done in the past. (If not in VBA, then Delphi, maybe?)
... but to my surprise, the dialog box appears again (although pressing F1 brings me to the official "Application.DisplayAlerts" documentation).
This leaves me with a simple question:
If a simple DisplayAlerts = ... does not equal Application.DisplayAlerts = ... anymore, what does it mean and how can I use it?
For your information, I'm working with Excel-365.
DisplayAlerts is an undeclared variable.
Certain Application properties and methods can (effectively) have the Application omitted:
ActiveCell, ActiveSheet, ActiveWorkbook, ActiveWindow, Addins, Charts, Selection, etc.
Calculate, Evaluate, Intersect, Run, Union, etc.
(but see this answer why/how this works):
A boolean property such as DisplayAlerts (EnableEvents, ScreenUpdating, etc) doesn't fall into the above category.
A golden rule in order not to fall into such a trap is the usage of Option Explicit while writing macros.
Just to add some information to the answer of #BigBen. If you write something like Workbooks or ActiveSheet in your code, VBA is not looking into the Application-object - it is looking into a (rather well hidden) object named Global.
The global object is exposing some (but not all) properties and methods of the Application-object, so ActiveSheet is referring to Application.ActiveSheet - but not because the Application has a member with this name but because the Global object defines that ActiveSheet means Application.ActiveSheet. In fact even the Application-object is accessed via the Global object.
There is hardly any information about this Global object or its concept. I found a page from Microsoft describing the Global object of MS Word, but the only explanation there is "Contains top-level properties and methods that don't need to be preceded by the Application property.". For Excel, I found this page on O'Reilly.
From time to time you get strange error messages like "Excel VBA Method 'Range' of object'_global' failed" - this is a pointer to the Global object. I would be glad to learn more about the concepts and mechanics of this object, but I am afraid that there are only very few people around that know more (except of course Mathieu Guindon AKA Mr. Rubberduck...). In daily life, we take it for granted that things like ActiveSheet simply works.

How to check file lock on .txt file before opening

Long story short... I am using a pc to open a .txt file located on a server... but sometimes the .txt file is not finished (there is still data stored in a buffer of the source computer).
FilePath = "D:\test.txt"
Workbooks.Open(Filename:=FilePath, ReadOnly:=True, IgnoreReadOnlyRecommended:=True)
Someone smarter than I am has identified that the .txt file is "locked" by the operating system until it is finished but I am still able to open it. I would like to wait for the .txt file to be "not locked" before opening it. How do I do this?
Note: The "smarter" person than me explained... the .txt file can be opened by a "dumb" program like "notepad" but if you try to use "Microsoft Word" to open it... you get a message telling you that it is locked...
import time
is_open = False
while not(is_open):
try:
f = open('test.txt','w')
is_open=True
except:
time.sleep(1)
I don't know how well the code below will work for your scenario.
You could change the constants into parameters (if you think their values need to change/be determined dynamically).
You could also change the GetFileOrWait's implementation such that it allows an infinite loop (I chose to avoid this, but maybe you want this).
All in all, the below is basically a function which tries to return the workbook in 120 seconds (or times out with an error) -- which you can hopefully use in a parent subroutine/procedure.
You may be able to specify finer frequencies (seconds may be too coarse) by using Timer instead or other lower level APIs.
Option Explicit
Private Function GetFileOrNothing() As Workbook
Const FILE_PATH As String = "D:\test.txt" ' Could pass this in as argument (if needed).
On Error Resume Next
Set GetFileOrNothing = Workbooks.Open(Filename:=FILE_PATH, ReadOnly:=True, IgnoreReadOnlyRecommended:=True)
On Error GoTo 0
End Function
Private Function GetFileOrWait() As Workbook
' Attempts to open a file. If access fails, waits n seconds before trying again.
' This function raises an error (times out to prevent infinite loop) after N seconds.
Const MAXIMUM_WAIT_IN_SECONDS As Long = 10
Const INTERVAL_WAIT_IN_SECONDS As Long = 1
Dim timeToStopAt As Date
timeToStopAt = DateAdd("s", MAXIMUM_WAIT_IN_SECONDS, Now)
Do While Now < timeToStopAt
Dim outputWorkbook As Workbook
Set outputWorkbook = GetFileOrNothing()
If Not (outputWorkbook Is Nothing) Then Exit Do
Application.Wait DateAdd("s", INTERVAL_WAIT_IN_SECONDS, Now)
DoEvents
Loop
If outputWorkbook Is Nothing Then
Err.Raise vbObjectError + 5, , "Failed to access file within the specified time frame."
End If
Set GetFileOrWait = outputWorkbook
End Function

VBscript and Excel: Opening and closing Excel objects - Arraylist preventing closing of object

I've got a problem with a vbscript which creates Excel objects and reads from an Excel file.
The vbscript is executed from an Excel macro, and then creates and opens the Excel file and reads from it. The problem is that the Excel object isn't allways closed, even though I'm trying to to it.
Here's the code from the vbscript:
Set ExcelObject = createobject("Excel.Application")
ExcelObject.workbooks.open testWorkBookPath
Set testActionArray = CreateObject( "System.Collections.ArrayList" )
Function getTestsCaseActions (testsPath, esheet, row, col)
Set my_sheet = ExcelObject.sheets.item(esheet)
tempArray = array(my_sheet.cells(row, col-2), "")
testActionArray.Add tempArray
Do While my_sheet.cells(row, col).Value <> ""
tempArray = array(my_sheet.cells(row, col), my_sheet.cells(row+1, col))
testActionArray.Add tempArray
col = col+1
Loop
End Function
getTestsCaseActions testWorkBookPath, testCaseSheet, 3, 4
ExcelObject.Quit
Now, if I run the above code and watch the process explorer, a new Excel process is spawned when the script is started, and then closes, as expected.
However, if I insert this code after running the function, before the ExcelObject.Quit line:
For Each ArrayItem in testActionArray
IF ArrayItem(1) = "" Then
Wscript.Echo ArrayItem(0)
Else
Wscript.Echo ArrayItem(0) & " -> " & ArrayItem(1)
End If
Next
ExcelObject.Quit (STILL HERE)
then the spawned process does NOT quit, and the process list grows until Excel goes completely bananas.
I don't understand this; All the last bit of code does is loop through the ArrayList and print the contents. Why's not the process quitting?
EDIT: At seems that at least some of the Excel objects eventually disappear from the Process Explorer, but this takes about 20-30 minutes. And it's just a few of them - most are still there. At least my list at the moment has shrinked some, but there are still about 15 Excel processes running.
Also, suddenly this message appears:
File Now Available
'filename.xlsm ' is now available for editing. Choose Read-Write to open it for editing.
This line seems to help. It doesn't completely remove all extra processes, but the number grows to five, then goes back to two, and so on. So it works pretty well.
dim book: for each book in ExcelObject.Workbooks: book.saved = true: next

Excel error 1004 "Unable to get .... property of WorksheetFunction class" appearing inconsistently

I have a VBA function within a spreadsheet which operates on another spreadsheet that is opened in an earlier stage of my macro. The macro used to work fine but just recently has started causing a 1004 error ("Unable to get RoundDown property of the WorksheetFunction class") when it runs.
I believe I understand what the error would be caused by (a problem running RoundDown) but I cannot see why it is getting triggered in my macro and the odd part is that when I go into Debug mode and step through the code in the VBE the error does not recur (despite nothing obviously changing).
Does anyone have a similar experience of this sort of error occuring inconsistently and know what I could do to resolve it?
I'm reasonably VBA/Excel-savvy, but any suggestions on further steps to diagnose it would be appreciated. I am wondering if there is some issue with the opened spreadsheet not being ready but I cannot see how.
The code is here. The error occurs on the line marked with a comment.
Public Function GetDatesA(sWorkbookname As String, sSheetname As String, sCell As String) As Variant
Dim vDateList() As Variant
Dim currentCell As Range
Dim n As Long
Set currentCell = Workbooks(sWorkbookname).Worksheets(sSheetname).Range(sCell)
n = 0
Do
If Trim(currentCell.Value) = "" Then
Exit Do
Else
ReDim Preserve vDateList(0 To 1, 0 To n)
vDateList(0, n) = WorksheetFunction.RoundDown(currentCell.Value, 0) 'error occcurs on this line
vDateList(1, n) = currentCell.Column
'Debug.Print currentCell.Value
End If
Set currentCell = currentCell.Offset(0, 1)
n = n + 1
Loop While currentCell.Column < XL_LAST_COLUMN
GetDatesA = vDateList
End Function
Other details are:
Excel version: 2010
File being opened resides locally on my C: drive; my macro is in a spreadsheet on the network
File format for both files is .xls (i.e. Excel 2003) - I don't have the option of changing this
Windows 7 (not that I think it would be relevant)
Two points I've tried already are:
Substitute a different worksheet function (e.g. Min(currentCell)) and that also causes the same problem
Having the file open already seems to stop the problem - I wonder if there is some way that the workbook which is being opened (rather than my main workbook with the macro in it) is not enabled for macros and this is interfering. But even if this is the cause I'm not sure how to get around it!
Any ideas?
This error occurs often when any argument passed to the worksheet function is not of the correct type or simply doesn't make sense.
For example, I've had this problem when calling WorksheetFunction.Asin with an argument bigger than 1. In your case, I'd guess currentCell.Value is a non-numeric value or one not according to your region settings regarding numbers.
Yes, the error message is really misguiding.
I got the "Unable to get * property of WorksheetFunction Class" error using Transpose, MMult,MDterm, and MInverse functions.
I was able to get my code to run by putting "Option Base 1" in the Declarations (before the actual code) section of the particular Module in the Editer.
Excel assumes "Option Base 0" which will add an extra row and column of empty cells. This will cause the error to occur and isn't immediately obvious to see.
I have come accross this before, and for me it was becase the criteria range made no sense, as Andre said above.
See example formula below:
.Cells(11, i).Formula = Application.WorksheetFunction.CountIfs(Sheets("Sheet1").Range("AC8:C" & n), "S")
Have a look at the Range... it makes no sense. Amended the range from "AC8:C" to "AC8:AC" and it will work perfectly

OLE Excel object manipulation causes run-time error '91'

I am maintaining an application that was written in Visual Basic 6.0 and makes use of the several OLE controls with Excel.Sheet.8 class objects. Several users are getting the following error when they reach a point in code that attempts to manipulate the excel objects.
Run-time error '91': Object variable or With block variable not set
Below are examples of the code that trigger this error. I believe that the issue happens at:
Set oExcel = oleXl.object
Here are the points in the code where it happens:
Private Sub Form_Load()
Dim i As Integer
Dim j As Integer
Dim sTempStringA As String
Dim sTempStringB As String
'Set up excel sheet
centerform Me
Set oOutGrid = oleXlOutput.object
...
Private Sub Form_Load()
centerform Me
Set oOtherFx = oleXlFx.object
...
Private Sub Form_Load()
Dim iRet As Integer
Dim i As Integer
On Error GoTo Err_Handler
centerform Me
Call InitArray
Me.Caption = "TJUJ | Version " & version & " | Enter Custom Fx"
Set oBook = oleExcel.object
...
Is there a specific situation or environment in which this error would be generated from this line of code OR a way that I can ensure the object will always be accessible at this point in the code?
The error only happens occasionally, and I can't reproduce it on my developer machine at all. I also do not have access to the machines that it is happening on, but it seems to be encountered when there is an instance of the EXCEL.EXE process running.
When you get runtime-error 91, you can bet there's an uninitialized object somewhere in the statement. In other words, you are trying to use the properties or methods of a variable/object with a value of Nothing.
In your examples, oleXl, oleXlFx, and oleExcel are probably Nothing. So when you refer to their .object property, you trigger the RTE.
Somewhere in your code these variables have to be initialized to something. Look for statements like Set oleXl = CreateObject("Excel.Application") or Set oleXl = New Excel.Application
One suggestion; when you find the statements that actually initialize those OLE objects, check to see how the error-handling is coded. If you see things like this:
On Error Resume Next
Set oleXl = CreateObject(...
add a test to make sure the object was instantiated
On Error Resume Next
Set oleXl = CreateObject(...
If oleXl Is Nothing Then
MsgBox "Hey, my object is Nothing!"
End If
Microsoft suggests that we can fix error 91 by creating a new registry key. To create a new key follow the steps below.
Click on the Windows Start menu
Type Regedit in the search box
Press Enter
Locate the following entry in the registry. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Transaction Server
Now select the transaction server and right click on it
Select New and then choose Key
Name the key as Debug
Right click on the Debug key and choose New
Now select Key and name the key as RunWithoutContext
Ref: http://backspacetab.com/error-91/

Resources