How to read/set Excel Textbox property from MS-Access VBA - excel

I have a simple Textbox in Excel worksheet (.xlsx) where I can read the BackColor property in Excel VBA sub with:
Debug.Print TextBox1.BackColor
I'm trying to reference that same textbox from MS-Access using the Excel 16 Object Model, but it can't see the textbox under any of the Excel Worksheet objects I'm looking at
It errors out on the line marked with asterisks below with error message
Method or Data Member Not Found
Public Sub SetHexColor()
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Set xlApp = GetObject(, "Excel.Application")
Set xlBook = Workbooks.Open("C:\Users\.........\Documents\TextBox.xlsx")
Set xlSheet = xlBook.Worksheets(1)
**Debug.Print xlSheet.TextBox1.BackColor**
Set xlSheet = Nothing
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
Is there another way to reference and preferably set properties of a Textbox control in Excel?
I'd prefer not to have call an Excel function to set the property if possible - or maybe that's the issue - it has to be an xlsm file?

Excel.Worksheet is a generic worksheet object - it only provides access to "out of the box" methods of the Worksheet object: if you've "subclassed" your worksheet by adding members such as TextBox1 then you can't access those added members via the generic Worksheet type.
You can either do this
Dim xlSheet As Object
or leave the declaration as-is, and use something like
Debug.Print xlSheet.OLEObjects("TextBox1").Object.BackColor
Note this is not specific to automating Excel from access VBA - the same would be true if working entirely within Excel.

Related

Run Excel VBA in Access

I have been researching this a great deal and I am not finding any leads to how this would work.
I have written code in Excel that I want to run in MS Access. I have pasted the code I wish to run in Access.
All the examples or information I have found is from 2003 Access. I am using 2016 Access.
The Excel code
Public Function getworkbook()
' Get workbook...
Dim ws As Worksheet
Dim Filter As String
Dim targetWorkbook As Workbook, wb As Workbook
Dim Ret As Variant
Application.DisplayAlerts = False
Sheets("DATA").Delete
' Sheets("DATA").Cells.Clear
Set targetWorkbook = Application.ActiveWorkbook
' get the customer workbook
Filter = "Text files (*.xlsx;*.xlsb),*.xlsx;*.xlsb"
Caption = "Please Select an input file "
Ret = Application.GetOpenFilename(Filter, , Caption)
If Ret = False Then Exit Function
Set wb = Workbooks.Open(Ret)
wb.Sheets(1).Move After:=targetWorkbook.Sheets(targetWorkbook.Sheets.Count)
' ActiveSheet.Paste = "DATA"
ActiveSheet.Name = "DATA"
ThisWorkbook.RefreshAll
' Application.Quit
Application.DisplayAlerts = True
End Function
Code I found and tried to use in Access.
Public Function runExcelMacro(wkbookPath)
Dim XL As Object
Set XL = CreateObject("Excel.Application")
With XL
.Visible = False
.displayalerts = False
.Workbooks.Open wkbookPath
'Write your Excel formatting, the line below is an example
.Range("C2").value = "=1+2"
.ActiveWorkbook.Close (True)
.Quit
End With
Set XL = Nothing
End Function
There are few concepts you need to deal with first.
Library references and scope
Your original code was written in Excel. Therefore, in that VBA project, it has Excel object referenced. In your Access VBA project, that is not referenced. You can compare this by looking at Tools -> References.
That brings us to the concept of "early-binding" and "late-binding". When you type in things like Range., you get VBA's intellisense to tell you what you can do with a Range or whatever. But in Access, you don't have Excel object library referenced by default. Therefore, Range. will not yield intellisense and you can't run the code because Access does not have Range in its object model and your VBA project mostly likely don't have a reference that has it.
Therefore, your code need to be adjusted to run late-bound if you do not want to add reference to Excel object model, and you most likely do want that anyway.
Unqualified Reference
Your original Excel code contains unqualified references to various global objects that are available in Excel's object model.
Application.DisplayAlerts = False
...
Sheets("DATA").Delete
...
Set wb = Workbooks.Open(Ret)
...
Those won't necessarily work consistently in VBA projects hosted by other hosts other than Excel and most certainly won't work in late-bound code. Furthermore, if you elect to add a reference to Excel's object model, you still end up leaking Excel instance which can cause ghost instances because unqualified references to the global objects will implicitly create an Excel instance that you can't interact and that can also cause other runtime error down the path. To make your code more late-bindable, you need something like:
Set ExcelApp = CreateObject("Excel.Application")
ExcelApp.DisplayAlerts = False
...
Set MyBook = ExcelApp.Workbooks("Whatever")
MyBook.Sheets("DATA").Delete
...
Set wb = ExcelApp.Workbooks.Open(Ret)
...
Note how all global objects that you could have accessed in a Excel-hosted context now have to be a variable on its own. Furthermore, you won't have access to ThisWorkbook or even Sheet1 in other VBA projects because Excel is no longer the host. You must adjust accordingly.
Switching between early-binding & late-binding
Early-bound code makes it much easier for you to develop since you get full intelisense and object browser helping you write the code. However, when referencing other object models, you might want to distribute your VBA code using late-binding to avoid versioning problems and broken references. But you can have best from both worlds:
#Const EarlyBind = 1
#If EarlyBind Then
Dim ExcelApp As Excel.Application
#Else
Dim ExcelApp As Object
#End If
Set ExcelApp = CreateObject("Excel.Application")
This illustrates the use of conditional compilation argument to allow you to have ExcelApp variable that can be either Excel.Application (aka early-bound) vs. Object (aka late-bound). To change, you simply change the Const LateBind line between 0 or 1.
First, to clear up terminology:
VBA is a separate language and not tied to any MS Office application. Under Tools\References, you will see Visual Basic for Applications is usually the first checked object. What differs between running VBA inside Excel, Access, Word, Outlook, etc. is the default access to their object library. Specifically:
Only Excel sees Workbook, Worksheet, etc. without defining its source
Only Access sees Forms, Reports, etc. without defining its source
Only Word sees Documents, Paragraphs, etc. without defining its source
When running a foreign object library inside an application, such as MS Access accessing Excel objects, you must define and initialize the foreign objects via reference either with early or late binding:
' EARLY BINDING, REQUIRES EXCEL OFFICE LIBRARY UNDER REFERENCES
Dim xlApp As Excel.Application
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Set xlApp = New Excel.Application
Set wb = xlApp.Workbooks.Open(...)
Set ws = wb.Worksheets(1)
' LATE BINDING, DOES NOT REQUIRE EXCEL OFFICE LIBRARY UNDER REFERENCES
Dim xlApp As Object, wb As Object, ws As Object
Set xlApp = CreateObject("Excel.Application")
Set wb = xlApp.Workbooks.Open(...)
Set ws = wb.Worksheets(1)
With that said, simply keep original code nearly intact but change definitions and initializations. Notably, all Application calls now point to Excel.Application object and not to be confused with Access' application. Plus, best practices of avoiding .Select/ .Activate/ Selection/ ActiveCell/ ActiveSheet/ ActiveWorkbook.
Public Function getworkbook()
' Get workbook...
Dim xlApp As Object, targetWorkbook As Object, wb As Object, ws As Object
Dim Filter As String, Caption As String
Dim Ret As Variant
Set xlApp = CreateObject("Excel.Application")
Set targetWorkbook = xlApp.Workbooks.Open("C:\Path\To\Workbook.xlsx")
xlApp.DisplayAlerts = False
targetWorkbook.Sheets("DATA").Delete
' get the customer workbook
Filter = "Text files (*.xlsx;*.xlsb),*.xlsx;*.xlsb"
Caption = "Please Select an input file "
Ret = xlApp.GetOpenFilename(Filter, , Caption)
If Ret = False Then Exit Function
Set wb = xlApp.Workbooks.Open(Ret)
wb.Sheets(1).Move After:=targetWorkbook.Sheets(targetWorkbook.Sheets.Count)
Set ws = targetWorkbook.Worksheets(targetWorkbook.Sheets.Count)
ws.Name = "DATA"
targetWorkbook.RefreshAll
xlApp.DisplayAlerts = True
xlApp.Visible = True ' LAUNCH EXCEL APP TO SCREEN
' xlApp.Quit
' RELEASE RESOURCEES
Set ws = Nothing: Set wb = Nothing: Set targetWorkbook = Nothing: Set xlApp = Nothing
End Function
By the way, above can be run in any MS Office application as no object of the parent application (here being MS Access) is used!

Open Excel OLEObject in a new Excel instance

I just learned to open programmatically embedded OLEObjects by following VBA-Excel code:
mySheet.OLEObjects(myName).Verb xlVerbOpen
However, if "myName" corresponds to an Excel object, the Excel file is opened in the same Excel instance in which I am running the program. Since at that time there are a couple of forms opened, I would like this object to be opened in a new Excel instance (and not behind the forms, as it is now happening). Is this possible? How could I do it? Thanks a lot in advance.
You can create new Excel Instance in your code (in the below sample - xlApp) and refer to that instance in whatever you do next (however this will work only if OLEObject is created with link):
Dim xlApp As New Excel.Application, xlWb As Workbook
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True 'Make new instance visible (by default it's not visible)
Set xlWb = xlApp.Workbooks.Open(Filename) ' Filename is path to the linked workbook
If OLEObject is not linked the only way to open in new Excel instance is to open with the main excel file, which is not what you want:
xlApp.Workbooks.Open(workbookpath).Worksheets("mySheet").OLEObjects(myName).Verb xlVerbOpen
Following Richard's suggestion, see below the code I built to be able to open an embedded excel object through VBA in a new workbook within a new Excel instance:
Dim xlApp As excel.Application
Dim xlWb As Workbook
Dim mySheet As Worksheet
Dim myName as String
Set mySheet = Sheets("write sheet name")
Set myName = Sheets("write object name")
ThisWorkbook.Sheets(mySheet).OLEObjects(myName).Copy
Set xlApp = New excel.Application
xlApp.Visible = True
Set xlWb = xlApp.Workbooks.Add
xlWb.Sheets(1).Paste
xlWb.Sheets(1).OLEObjects(myName).Verb xlVerbOpen
Regards

How to efficiently remove empty Excel rows using VBS?

I need to remove the whole row IF column A value is empty. I have been doing it in excel and this method works best for me
.Columns("a:a").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
I need to do the same thing using vbs however, I have issues converting it to vbs
How can I convert the above line into vbs?
I looked up the xlCellTypeBlanks = 4 using F2 . But how to use the SpecialCells method ?
Something like this
Const xlCellTypeBlanks = 4
Dim xlApp
Dim xlwb
Set xlApp = CreateObject("Excel.Application")
Set xlwb = xlApp.workbooks.Open("C:\temp\test.xlsm")
On Error Resume Next
xlwb.Sheets(1).Columns("a:a").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
You will need to have an object for the Excel App, Workbook, Worksheet etc.. So something like
Dim xlApp as Object
Set xlApp = CreateObject("Excel.Application")
Dim wb as object
Set wb = xlApp.Open("YourWorbookName.xlsx")
wb.Worksheets("NameOfWorksheet").Columns("a:a").SpecialCells(xlCellTypeBlanks).EntireRow.Delete

how to print excel file via vb6?

I have an excel file that was created by vb6 application and after I save it, I want it to be printed into the default printer..,
Tnx, any help would be appreciated.
Private Sub Command1_Click()
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim xlSH As Excel.Worksheet
'open excel application
Set xlApp = New Excel.Application
'Open excel workbook
Set xlWB = xlApp.Workbooks.Open(FileName:="C:\YourFile.xls")
'There are two ways to access specific worksheets
'By index number (the first worksheet in this case)
Set xlSH = xlWB.Worksheets(1)
'or by the Sheet's Name
Set xlSH = xlWB.Worksheets("TestSheet")
PrintSheet xlSH, "MyFoot", "MyHead"
'Close workbook (optional)
xlWB.Close
'Quit excel (automatically closes all workbooks)
xlApp.Quit
'Clean up memory (you must do this)
Set xlWB = Nothing
Set xlApp = Nothing
End Sub
Sub PrintSheet(sh As Worksheet, strFooter As String, strHeader As String)
sh.PageSetup.CenterFooter = strFooter
sh.PageSetup.CenterHeader = strHeader
sh.PrintOut
End Sub
Yet, to answer your question, you can use :
ActiveWorkbook.PrintOut Copies:=1, Collate:=True
and you can find much information here : http://www.exceltip.com/excel_tips/Printing_in_VBA/210.html
Anyway, i insist, you should accept answers from your previous questions or people won't care answering your new ones.
Max

Exchanging variables between powerpoint and excel VBA

I have a powerpoint pres that grabs some data from an excel sheet when a button is pressed.
Set EXL = New Excel.Application
EXL.Visible = False
Dim XLApp As Excel.Application
Set XLApp = GetObject(, "Excel.Application")
This is how I set the new excel application.
What I'm wondering is how I can send over a variable from my powerpoint slide into the excel workbook? I have textfield in my powerpoint slide that I want the text to be used in a variable inside excel. Is this possible? If so, how?
And how do I, from a powerpoint module, call a Sub within the excel workbook to run?
(This is some simplified production code from an Access db, powerpoint might have a few minor differences)
What I'm wondering is how I can send over a variable from my powerpoint slide into the excel workbook?
Sub SetXLCellValue( _
FileStr As String, _
TabStr As String, _
Cell As String)
Dim XLApp As New Excel.Application
Dim ObjXL As Excel.Workbook
Set ObjXL = XLApp.Workbooks.Open(FileStr)
ObjXL.Worksheets(TabStr).Range(Cell).value = value
ObjXL.Save
ObjXL.Close True
End Sub
As for calling a Sub in your Excel application, you can use
XLApp.Run("MySub")
This also has the ability to pass parameters to the method (intellisense should show you the way)

Resources