Call excel function in access vba - excel

I've a sub in excel that needs to be called from access.
Excel vba
Public Function testme(value As String) As String
Dim xlpath As String
Dim concate As String
xlpath=ActiveWorkbook.Path
value = ActiveWorkbook.Name
concate = xlpath & "\" & value
Let testme = concate
End Function
i need to call above method in one of the access method.How do i call it.
Sub Connect1()
Dim xlApp As Variant
'Set xlApp = CreateObject("Excel.Application")
'this will launch a blank copy of excel; you'll have to load workbooks
'xlApp.Visible = True
Set xlApp = GetObject(, "Excel.Application")
Let ans = xlApp.Application.Run("MyXLVBAProject.MyXLVBAModule.testme", 400)
'here ans has the string "500"
End Sub

You'll probably want to use Application.Run from Excel's object model. You pass it a string such as "QuickRDA.JavaCallBacks.GetQuickTab" for the macro name, where QuickRDA is the name of the Excel VBA project, JavaCallBacks is the name of the VBA module in that VBA project, and GetQuickTab is the name of the function in that VBA module.
In Access
Sub Connect()
Dim xlApp As Variant
Set xlApp = GetObject(, "Excel.Application")
'this will connect to an already open copy of excel, a bit easier for quick & dirty testing
Let ans = xlApp.Application.Run("MyXLVBAProject.MyXLVBAModule.testme")
End Sub
In Excel
Public Function testme() As String
Dim xlpath As String
Dim concate As String
Dim value as String
xlpath = ActiveWorkbook.Path
value = ActiveWorkbook.Name
concate = xlpath & "\" & value
Let testme = concate
End Function
-or simply-
Public Function testme() As String
Let testme = ActiveWorkbook.FullName
End Function
Remember that in Excel the function testme should be put in a module whose name is MyXLVBAModule, and that the project containing the module should be called MyXLVBAProject.

So, you want to trigger an Excel function from Access, or run an Excel subroutine from Access?
To run a function, you can do something like this.
Public Function FV(dblRate As Double, intNper As Integer, _
dblPmt As Double, dblPv As Double, _
intType As Integer) As Double
Dim xl As Object
Set xl = CreateObject("Excel.Application")
FV = xl.WorksheetFunction.FV(dblRate, intNper, dblPmt, dblPv, intType)
Set xl = Nothing
End Function
To run an Excel subroutine from Access, you can do the following.
Sub RunExcelMacro()
Dim xl As Object
'Step 1: Start Excel, then open the target workbook.
Set xl = CreateObject("Excel.Application")
xl.Workbooks.Open ("C:\Book1.xlsm")
'Step 2: Make Excel visible
xl.Visible = True
'Step 3: Run the target macro
xl.Run "MyMacro"
'Step 4: Close and save the workbook, then close Excel
xl.ActiveWorkbook.Close (True)
xl.Quit
'Step 5: Memory Clean up.
Set xl = Nothing
End Sub

Related

Pull particular Excel cell value into Word document using Word VBA

I am new to VBA and macros.
I got the repeated task of copy data from Excel and paste it in a particular location in the word document.
For example, my excel sheet has the data like this:
Col1
Col2
ID_1
I'm_One
ID_2
I'm_Two
ID_3
I'm_Three
Now i'm looking for a Word macro
Get text in Word table with cell position 3
Find the same text in Excel Col1
Get the value of Col2 from Excel
Paste the value of Col2 in word table with cell position 10
Repeat the same process for another table in Word document
[Update]
I have tried with multiple code snippets by google search but unable to construct the working macro.
Sub pull_from_Excel2()
'ref: https://www.macworld.com/article/211753/excelwordvisualbasic.html
Dim Month As String
ID_Range = "A2:A6" 'Select this as range like "A2:A16"
Offset_to_fetch = 1 'Select this to fetch comments etc. value starts with
Set xlSheet = GetObject("D:\Excel.xlsx")
'Snippets:
'Debug.Print VarType(xlSheet.Worksheets("Sheet1").Range("A3:A5").Value)
'8204
Dim Cell As Range, rng As Range
Debug.Print VarType(xlSheet.Worksheets("Sheet1").Range(ID_Range).Value2)
Set rng = xlSheet.Worksheets(1).Range(ID_Range)
For Each Cell In rng
Debug.Print Cell.Text
Next Cell
End Sub
I used this url to construct my skeleton code: https://www.macworld.com/article/211753/excelwordvisualbasic.html
When i try to get the values from the range of cells in excel, i got the following error for the code.
Set rng = xlSheet.Worksheets(1).Range(ID_Range).Value2
The above line gives "Object required" error when running.
Set rng = xlSheet.Worksheets(1).Range(ID_Range)
The above line gives "Type Mismatch" error when running.
Notes: For this error, I tried to use for each loop as this is array but the error is showing before executing the for loop.
Kindly assist.
I recommend to use Option Explicit and declare all your varibales properly. This way it is less likely that you end up with unseen errors.
To activate it for all new codes that you add in the future, you can activate it directly in Excel and Word. This is a good practice and will protect you from doing it wrong by notifying you of not declared variables:
In the VBA editor go to Tools › Options › Require Variable Declaration.
This will add Option Explicit to new modules only. In existing modules Option Explicit needs to be added manually as first line.
Further I highly recommend to name your variables according what they contain because otherwise it gets very confusing. You named your variable xlSheet but you load a workbook into it and not a worksheet.
The next issue is that your code is in Word and if you declare rng As Range then this is of type Word.Range and not Excel.Range and those are diffetent types so that is why you get a "Type Mismatch" error.
To solve this you either go in Word VBA to Extras › Refereces … and set a reference to the Excel library so you can declare your variable Dim xlRng As Excel.Range or if you don't set a reference you declare it as Object or Variant like in below example:
' This code is in Word!
Option Explicit
Public Sub pull_from_Excel2()
'declare constants
Const ID_Range As Sting = "A2:A6" 'Select this as range like "A2:A16"
Const Offset_to_fetch As Long = 1 'Select this to fetch comments etc. value starts with
Dim xlWorkbook As Object
Set xlWorkbook = GetObject("D:\Excel.xlsx") 'This expects the Excel to be already open! If not open you need to use CreateObject("Excel.Application")
Dim xlRng As Object
Set xlRng = xlWorkbook.Worksheets(1).Range(ID_Range)
Dim xlCell As Object
For Each xlCell In xlRng
Debug.Print xlCell.Text
Next xlCell
End Sub
Note if your workbook Set xlWorkbook = GetObject("D:\Excel.xlsx") is not open in Excel you need to use CreateObject("Excel.Application") and open it.
Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")
Dim xlWorkbook As Object
Set xlWorkbook = xlApp.Workbooks.Open(FileName:="D:\Excel.xlsx") 'will open the workbook
xlApp.Visible = True 'make it false to open Excel invisible in the background
'your code here …
'in the end close workbook and Excel (espaciall if you had it invisible!)
xlWorkbook.Close SaveChanges:=False
xlApp.Quit 'close Excel
Option Explicit
Sub UpdateTables()
Const XLSX = "D:\Excel.xlsx"
Dim xlApp, wb, ws
Dim rngSearch, rngFound
Dim iLastRow As Long, n As Integer
' open spreadsheet
'Set xlApp = New Excel.Application
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
Set wb = xlApp.Workbooks.Open(XLSX, 1, 1)
Set ws = wb.Sheets(1)
iLastRow = ws.Cells(ws.Rows.Count, "A").End(-4162).Row 'xlUp
Set rngSearch = ws.Range("A2:A" & iLastRow)
' update tables
Dim doc As Document, tbl As Table, s As String
Set doc = ThisDocument
For Each tbl In doc.Tables
s = tbl.Cell(1, 1).Range.Text
s = Left(s, Len(s) - 2)
Set rngFound = rngSearch.Find(s, LookIn:=-4163, LookAt:=1) ' xlValues, xlWhole
If rngFound Is Nothing Then
MsgBox "'" & s & "' not found in table " & tbl.Title, vbExclamation
Else
tbl.Range.Cells(3).Range.Text = rngFound.Offset(0, 1)
n = n + 1
End If
Next
wb.Close False
xlApp.Quit
MsgBox n & " tables updated", vbInformation
End Sub

Can't properly close Excel application

i am very new to VB.net and i'm trying to proceed step by step with my application.
The application i'm trying to build will collect a series of macros i've written in Excel VBA environment.
Now, the following code pasted below, is the initial part, where basically i try to load a workbook (to be used as Active workbook) and to "unload it".
The issue comes when, after "unloading" the workbook, i try to open the very same workbook in excel.
Excel application return an error that is "Open in read-only". This cannot be accepted, and i need to understand how to unload the workbook and release it from the myAPP.
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Dim workbook As Excel.Workbook
Dim worksheet As Excel.Worksheet
Dim APP As New Excel.Application
Private Sub opn_btn_Click(sender As Object, e As EventArgs) Handles opn_btn.Click
Dim strname As String
Dim cellname As String
With OpenFileDialog1
.InitialDirectory = "E:\Vs_Excel"
.Title = "Open xlsx file"
.ShowDialog()
End With
workbook = APP.Workbooks.Open(OpenFileDialog1.FileName)
worksheet = workbook.Worksheets("sheet1")
cellname = worksheet.Range("A1").Value
strname = OpenFileDialog1.FileName
Me.TextBox1.Text = strname
Me.TextBox2.Text = cellname
Dim lvwReport As View = View.List
With Me.ListView1
.GridLines = True
.View = lvwReport
.CheckBoxes = True
End With
'LoadListView() 'thi sroutine is written but not used yet. Must solve first the problem wioth closing ExcelApplication
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
workbook.Close()
APP.Quit()
Me.TextBox1.Text = ""
Me.TextBox2.Text = ""
ReleaseObject(worksheet)
worksheet = Nothing
ReleaseObject(workbook)
workbook = Nothing
ReleaseObject(APP)
APP = Nothing
End Sub
Private Sub ReleaseObject(ByVal obj As Object)
Try
Dim intRel As Integer = 0
Do
intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Loop While intRel > 0
MsgBox("Final Released obj # " & intRel)
Catch ex As Exception
MsgBox("Error releasing object" & ex.ToString)
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End class

VBA Excel code working if called by button but not if called by function [duplicate]

This question already has an answer here:
Excel VBA: Answer gets "stuck"
(1 answer)
Closed 4 years ago.
I'm trying to open a file using a function. The same code is working if I call it by a button. The file will open, I can modify it and I can close it without saving. But if I use the same code called by the function the file will not be open. Why? Following the code used with the button and with the function. Might anyone help me? This is only the beginning of what I would need. Detailing, with this function I need to open a CSV file, fix the CSV file, extract a data with a Dlookup and write this data on the cell where I called the function. This works if I call my code by button but not if I call it with a function in a cell
Sub Button1_Click()
Dim path As String
Dim xl As Excel.Application
Dim wk As Excel.Workbook
path = ActiveWorkbook.path & "\Book1.xlsm"
Set xl = Excel.Application
Set wk = xl.Workbooks.Open(path)
xl.Visible = True
wk.Activate
xl.DisplayAlerts = False
Range("B2").Select
Range("B2").Value = "hello world"
wk.Saved = False
wk.Close
Set wk = Nothing
End sub
Public Function aprifile()
Dim path As String
Dim xl As Excel.Application
Dim wk As Excel.Workbook
path = ActiveWorkbook.path & "\Book1.xlsm"
Set xl = Excel.Application
Set wk = xl.Workbooks.Open(path)
xl.Visible = True
wk.Activate
xl.DisplayAlerts = False
Range("B2").Select
Range("B2").Value = "hello world"
wk.Saved = False
wk.Close
Set wk = Nothing
End Function
There's a couple of things here.
First I have made the thing a Sub rather than a Function as you're not returning anything.
Option Explicit
Public Sub aprifile()
Dim path As String
Dim xl As Application
Dim wk As Workbook
path = ActiveWorkbook.path & "\Book1.xlsm"
If Len(Dir$(path)) > 0 Then
Set xl = Excel.Application
Set wk = xl.Workbooks.Open(path)
xl.Visible = True
wk.Activate
xl.DisplayAlerts = False
wk.ActiveSheet.Range("B2").Select
wk.ActiveSheet.Range("B2").Value = "hello world"
wk.Saved = False
wk.Close
Set wk = Nothing
End If
End Sub
The second thing is that I placed 'wk.ActiveSheet' to make sure that I am writing to the correct sheet. Without that I found that I was writing to the wrong workbook.
The other thing I did, as you can see, I checked to see if the file existed. I found that for my first run it didn't so that may give you a clue there.
But, I can assure you that this code works because I've just done it here.
Hope that this helps
Malc

Access current ID field to Excel cell

Project Management
Project Details
This is a standard Project Management database, when ID number is pressed it goes to Project Details - pic2.
After that I inserted 2 buttons one for creating a folder and Excel button that opens a specific template.
Button one does this:
Private Sub Command85_Click()
Const strParent = "F:\2. Prodaja\"
Dim projectID As String
Dim strFolder As String
Dim fso As Object
' Get ID from control
projectID = Me.ID
' Full path
strFolder = strParent & projectID
' Create FileSystemObject
Set fso = CreateObject("Scripting.FileSystemObject")
' Check whether folder exists
If fso.FolderExists(strFolder) = False Then
' If not, create it
fso.CreateFolder strFolder
End If
' Open it
Shell "explorer.exe " & strFolder, vbNormalFocus
End Sub
And the Excel button:
Function OpenExcelFromAccess()
Dim MyXL As Object
Set MyXL = CreateObject("Excel.Application")
With MyXL
.Application.Visible = True
.Workbooks.Open "F:\0. Main\01.Templates\ponuda.xltm"
.Worksheets("Kupci").ListObjects("Employees__4").Refresh
Dim EmpID As Integer
EmpID = ID_Employees
.Worksheets("GlavnaTabela").Cells(3, 25).Value = EmpID
End With
End Function
The idea was to copy the ID_Employee number and paste it to cell Y3, but it doesn't give me the current number of ID_Employees, it gives me 0. First button works and creates folders based on ID. My question is how to get ID_employees from Access Form into Excel cell Y3?
I changed function to Sub and done these changes:
Private Sub Command166_Click()
Dim EmpID As Integer
If IsNull(ID_Employees) Then EmpID = 0 Else EmpID = ID_Employees
Set MyXL = CreateObject("Excel.Application")
With MyXL
.Application.Visible = True
.Workbooks.Open "F:\0. Main\01.Templates\ponuda.xltm"
.Worksheets("Kupci").ListObjects("Employees__4").Refresh
.Worksheets("GlavnaTabela").Cells(3, 25).Value = EmpID
End With
End Sub

VBA: Excel stops working after extracting data from other workbooks

I'm trying to extract data from other 4 workbooks (some of them may have thousands of rows)
The Excel stops working, and restarts, after the extraction is completed.
I have the data extracted in the sheets so I assume that the excel is chrashing after the last workbook data is extracted.
I also tested with only one workbook and it crashes after closing.
I have read that we could use "DoEvents" and "Application.Wait" after copy/paste or close workbook, to let Excel finish some background work. I've tried that but with no success.
Any ideas why the Excel stops running / restarts?
Here is my code:
Public sysExtractParamsDictionary As Scripting.dictionary
'Sub rotine triggered when pressing button
Sub Extract()
Set sysExtractParamsDictionary = mUtils.FillDictionary("sysParams", "tExtractParams") 'Sub rotine belonging to mUtils module to fill dictionary with values from my sysParams sheet. Contains the sheets name.
mClean.Clean 'Sub rotine belonging to mClean module to clear sheets
ExtractData [sysInputDirectory], "Input Sheet" 'Cell Name sysInputDirectory
ExtractData [sysR2Directory], "R1 Sheet"
ExtractData [sysR2Directory], "R2 Sheet"
ExtractData [sysR3Directory], "R3 Sheet"
End Sub
Sub ExtractData(sFilePath As String, sDictionaryKey As String)
Dim oWorkbook As cWorkBook 'Class Module
Set oWorkbook = New cWorkBook
mUtils.SetStatusBarMessage True, "Extracting " & sDictionaryKey & " ..." 'Sub rotine belonging to my mUtils module to set on or off status bar message
oWorkbook.WorkBookDirectory = sFilePath
oWorkbook.OpenWorkBook oWorkbook.WorkBookDirectory
oWorkbook.CopiesSourceSheetValuesToDestinationSheet sysExtractParamsDictionary(sDictionaryKey)
oWorkbook.CloseWorkBook (False)
DoEvents
DoEvents
Application.Wait (Now + TimeValue("0:00:05"))
DoEvents
Set oWorkbook = Nothing
End Sub
'#### Class Module
Private wbWorkBook As Workbook
Private sWorkBookDirectory As String
Private sWorkBookName As String
Private wsWorksheet As Worksheet
Public Property Set Workbook(wbNew As Workbook)
Set wbWorkBook = wbNew
End Property
Public Property Get Workbook() As Workbook
Set Workbook = wbWorkBook
End Property
Public Property Let WorkBookDirectory(sFilePath As String)
sWorkBookDirectory = sFilePath
End Property
Public Property Get WorkBookDirectory() As String
WorkBookDirectory = sWorkBookDirectory
End Property
Public Property Let WorkBookName(sFileName As String)
sWorkBookName = sFileName
End Property
Public Property Get WorkBookName() As String
WorkBookName = sWorkBookName
End Property
Public Property Set Worksheet(wsNew As Worksheet)
Set wsWorksheet = wsNew
End Property
Public Property Get Worksheet() As Worksheet
Worksheet = wsWorksheet
End Property
Public Property Let WorkBookDirectory(sFilePath As String)
sWorkBookDirectory = sFilePath
End Property
Public Property Get WorkBookDirectory() As String
WorkBookDirectory = sWorkBookDirectory
End Property
'Class Module Function to Open WorkBook
Public Sub OpenWorkBook(sFilePath As String)
Dim oFSO As New FileSystemObject
Dim sFileName As String
Dim sLog As String
sFileName = oFSO.GetFileName(sFilePath) 'Get the File Name from Path
If sFileName = "" Then
sLog = "Error. Not possible to retrieve File Name from Directory."
Else
Me.WorkBookName = sFileName
Set Me.Workbook = Workbooks.Open(sFilePath)
If wbWorkBook Is Nothing Then
sLog = "Error opening file: " & Me.WorkBookName
Else
sLog = "File successfully openned!"
End If
End If
Set oFSO = Nothing
End Sub
'Class Module Function to Copy Values from source to destination
Public Sub CopiesSourceSheetValuesToDestinationSheet(wsDestinationName As Variant)
Dim wsDestination As Worksheet
Dim rStartRange As range
Dim rFullRangeToPaste As range
Set wsDestination = ThisWorkbook.Sheets(CStr(wsDestinationName)) ' Destination Sheet
Set Me.Worksheet = Me.Workbook.Sheets(1) 'Source Sheet
Set rStartRange = wsWorksheet.range("A1")
Set rFullRangeToPaste = wsWorksheet.range(rStartRange, mUtils.FindLast(3)) 'FindLast is a function belonging to mUtils module to find the last cell in worksheet
rFullRangeToPaste.Copy wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp)
End Sub
'Class Module Function to Close Workbook
Public Sub CloseWorkBook(bSaveChanges As Boolean)
wbWorkBook.Saved = True
wbWorkBook.Close SaveChanges:=False
End Sub
'#### End Class Module
I've also tried to do it without Class Module (just in case something was wrong with objects), but i still have the same issue.
Sub Extract()
ExtractCopyClose "C:\MyFiles\InputData.csv", "Input"
End Sub
Sub ExtractCopyClose(sFilePath As String, wsDestinationName As String)
Dim wb As New Workbook
Dim wsDestination As Worksheet
Dim wsSource As Worksheet
Dim oFSO As New FileSystemObject
Dim sLog As String
Dim rStartRange As range
Dim rFullRangeToPaste As range
sFileName = oFSO.GetFileName(sFilePath) 'Get the File Name from Path
If sFileName = "" Then
sLog = "Error. Not possible to retrieve File Name from Directory."
Else
Set wb = Workbooks.Open(sFilePath)
If wb Is Nothing Then
sLog = "Error opening file: " & sWorkBookName
Else
sLog = "File successfully openned!"
End If
End If
Set oFSO = Nothing
Set wsDestination = ThisWorkbook.Sheets(wsDestinationName) ' Destination Sheet
Set wsSource = wb.Sheets(1) 'Source Sheet
Set rStartRange = wsSource.range("A1")
Set rFullRangeToPaste = wsSource.range(rStartRange, mUtils.FindLast(3))
rFullRangeToPaste.Copy wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp)
wb.Saved = True
wb.Close SaveChanges:=False
End Sub
I have found that the sheet I was importing from the other workbook had external connections and was creating Connections and new References in my Workbook. Don't know why, but somehow this was affecting my Excel and causing it to restart since I was copying all the sheet content.
Instead of copying the full source sheet to my workbook...
rFullRangeToPaste.Copy wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp)
I copied only the values and formats of the source sheet...
Dim rDestinationRange As Range
'the rest of the code in question
rFullRangeToPaste.Copy wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp)
Set rDestinationRange = wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp)
rFullRangeToPaste.Copy
wsDestination.PasteSpecial xlPasteValuesAndNumberFormats
Note: This worked after my workbook recovered from the previous extraction (without broken external connections and null references). Then I made the changes in the code and save it.

Resources