Excel daemon instance: Access VBA - excel

This problem has consumed a lot of my time now. Everytime I run code from access to launch excel read file location and then open the excel on that file location, make changes and close. I see that this leaves an orphan excel process. I have tried all ways of referencing and possible solutions suggested out on internet, but nothing to help. My code as below. Any help or suggestions would be great:
Public Sub productdetailprinter()
Dim i As Double
Dim dbs As DAO.Database
Dim recSet As Recordset
Dim wb As Workbook
Dim ws As Worksheet
Dim tableName As String
Dim recTable As Recordset
Dim fld As DAO.Field
Dim k As Integer
Dim r As Integer
Dim intformat As Integer
Dim wrksht As Worksheet
Dim wrkbk As Workbook
Dim filelocation As String
Dim xl As Excel.Application
Set xl = CreateObject("Excel.Application")
xl.Visible = True
Set dbs = CurrentDb
Set recSet = dbs.OpenRecordset("tbl_formList")
Set wrkbk = xl.Workbooks.Open("<location>")
Set wrksht = wrkbk.Worksheets("databaselinks")
filelocation = wrksht.Range("C5").Value
wrkbk.Close
xl.Quit
Set wrksht = Nothing
Set wrkbk = Nothing
Set xl = Nothing
Set xl = CreateObject("Excel.Application")
xl.Visible = True
xl.Workbooks.Application.DisplayAlerts = False
xl.Workbooks.Application.AskToUpdateLinks = False
Set wb = xl.Workbooks.Open(filelocation & "\product_detail.xlsx")
Set ws = wb.Worksheets("details")
xl.Workbooks.Application.AskToUpdateLinks = True
xl.Workbooks.Application.DisplayAlerts = True
ws.Range("B3", Range("B3").End(xlDown)).Select
xl.Selection.Clear
ws.Range("C3", Range("C3").End(xlDown)).Select
xl.Selection.Clear
ws.Range("D3", Range("D3").End(xlDown)).Select
xl.Selection.Clear
i = ws.Columns("B").End(xlDown).Row
i = i + 1
Do Until recSet.EOF
'code lines
recSet.MoveNext
Loop
ws.Save
wb.Close
xl.Quit
Set xl = Nothing
Set ws = Nothing
Set wb = Nothing
recTable.Close
recSet.Close
End Sub

You must close the objects in exact reverse order:
' Also:
Dim rng As Excel.Range
Set xl = CreateObject("Excel.Application")
xl.Visible = True
Set wrkbk = xl.Workbooks.Open("<location>")
Set wrksht = wrkbk.Worksheets("databaselinks")
Set rng = wrksht.Range("C5")
filelocation = rng.Value
Set rng = Nothing
Set wrksht = Nothing
wrkbk.Close
Set wrkbk = Nothing
xl.Quit
Set xl = Nothing
This is tested and works at me:
Public Sub EditWorkSheet()
Dim xls As Excel.Application
Dim wkb As Excel.Workbook
Dim wks As Excel.Worksheet
Dim rng As Excel.Range
Dim Column As Integer
Set xls = New Excel.Application
Set wkb = xls.Workbooks.Open("c:\test\test.xlsx")
Set wks = wkb.Worksheets(1)
Set rng = wks.Range("C5")
rng.Value = 4
wkb.Close True, "c:\test\test1.xlsx"
Set rng = Nothing
Set wks = Nothing
Set wkb = Nothing
xls.Quit
Set xls = Nothing
End Sub

Thank you for proposed solutions. After spending 4 hours on this.. I realized that vba wasnt happy with the way I was referencing the ranges.
ws.Range("B3", Range("B3").End(xlDown)).Select
should be referenced as
ws.Range(ws.Range("B3"), ws.Range("B3").End(xlDown)).Select
It works like a charm.. Excel instances die and no more errors.
Hope this saves someones time out there.
Thank You

Related

Retrieve data on Excel from Word VBA using Worksheetfunction

I am trying to automatically fill in tables in a MS word file by retrieving data in various excel tables. In order to properly interact with Excel it would be very handy to work with worksheetfunction. Yet since the macro is in MS Word I am getting blocked. Any way to access it? Cheers
Dim src As Workbook
Dim ws As Worksheet
Dim t As String
Dim c As Integer
t = ThisDocument.Tables(1).Cell(1, 1).Range.Text
t = Left(t, Len(t) - 1)
Set src = workbooks.Open("https://collab.ext.../asd.xlsx", True, True)
Set ws = src.Worksheets("Data")
c = worksheetfunction.Match(t, ws.Range("A1:AA1"), False)
src.Close
Set src = Nothing
#Tim Williams thanks for your help. Corrected code below:
Dim oXL As Object
Dim oWB As Workbook
Dim oWS As Worksheet
Dim wbPath As String
Dim t As String
Dim c As Integer
Set oXL = CreateObject("Excel.Application")
oXL.Visible = False
wbPath = "https://collab.ext...asd.xlsx"
t = ThisDocument.Tables(1).Cell(1, 1).Range.Text
t = Left(t, Len(t) - 2)
Set oWB = oXL.workbooks.Open(wbPath, True, True)
Set oWS = oWB.Sheets("Data")
c = oXL.worksheetfunction.Match(t, oWS.Range("A1:AA3"), False)
oXL.ActiveWorkbook.Close SaveChanges:=False
oXL.Application.Quit
Set oXL = Nothing
Set oWB = Nothing
Set oWS = Nothing

VBA Inserting Comments from Excel to Word

I'm new to VBA and I'm having difficulty trying to insert comments from data that I have in Excel onto a Word document. I am trying to write the VBA in Word and want it to extract data from a separate spreadsheet
Sub ConvertCelltoWordComment()
Dim Rng As Range
Dim wApp As Object
Dim strValue As String
Dim xlapp As Object
Dim xlsheet As Object
Dim xlbook As Object
'Opens Excel'
Set xlapp = GetObject("C:\Users\eugenechang\Desktop\...xlsx")
If Err Then
Set xlapp = CreateObject("Excel.Application")
End If
On Error GoTo 0
Dim i As Integer
For i = 1 To 5
With xlsheet
strValue = ActiveSheet.Cells(i, 1).Offset(1, 0)
End With
'Insert comment into document'
ActiveDocument.Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext, Name:="15"
ActiveDocument.Selection.GoTo What:=wdGoToLine, Which:=wdGoToRelative, Count:=5
ActiveDocument.Comments.Add Range:=Selection.Range, Text:=strValue
Next i
End Sub
I'm trying to get it to work, but it is giving me an error "Object not defined". I've tried setting up an object within the strValue line below "With xlsheet", but am hitting a wall. Any help??
You have not assigned anything to xlsheet - so this (by default) equates to Nothing.
Try setting xlSheet to something meaningful. The following is only an example:
For i = 1 To 5
Set xlsheet = xlbook.Worksheets(i) ' <--- example here
With xlsheet
strValue = .Cells(i, 1).Offset(1, 0) '<-- don't use ActiveSheet
End With
'Insert comment into document'
ActiveDocument.Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext, Name:="15"
ActiveDocument.Selection.GoTo What:=wdGoToLine, Which:=wdGoToRelative, Count:=5
ActiveDocument.Comments.Add Range:=Selection.Range, Text:=strValue
Next I
An important note here is that you also have not set xlbook - you must also assign something meaningful to xlbook.
Add a couple DocVariables to your Word file and run the script below, from Excel.
Sub PushToWord()
Dim objWord As New Word.Application
Dim doc As Word.Document
Dim bkmk As Word.Bookmark
sWdFileName = Application.GetOpenFilename(, , , , False)
Set doc = objWord.Documents.Open(sWdFileName)
'On Error Resume Next
objWord.ActiveDocument.variables("FirstName").Value = Range("FirstName").Value
objWord.ActiveDocument.variables("LastName").Value = Range("LastName").Value
' etc., etc., etc.
objWord.ActiveDocument.Fields.Update
'On Error Resume Next
objWord.Visible = True
End Sub
This ended up writing comments from an Excel file. Obviously the names have been changed for privacy reasons. Please let me know if I can simplify this better.
Sub ConvertExceltoWordComment()
Dim wApp As Word.Application
Dim xlApp As Excel.Application
Dim PgNum As Integer
Dim LineNum As Integer
Dim objSelection As Word.Document
Dim strpgSearch As Long
Dim strlinSearch As Long
Dim myRange As Range
Dim XlLog As Excel.Worksheet
Dim RowCount As Long
'Opens Copied Word document'
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
If Err Then
Set xlApp = CreateObject("Excel.Application")
End If
On Error GoTo 0
Dim SaveDoc As Excel.Workbook
Set SaveDoc = xlApp.Workbooks.Open("FilePath.xlsm") 'Type filepath of document here'
Set XlLog = SaveDoc.Sheets("Worksheet_Name") 'Type Sheetname here'
RowCount = XlLog.Range("A1048576").End(xlUp).Row
If RowCount > 0 Then
Dim iTotalRows As Long
iTotalRows = XlLog.Rows.Count 'Get total rows in the table'
Dim txt As Variant
Dim iRows As Long
End If
Dim i As Integer
'Insert comment into Word document'
Set wApp = CreateObject("Word.Application")
wApp.Visible = True
If Err Then
Set wApp = CreateObject("Word.Application")
End If
Set objSelection = ActiveDocument
For iRows = 3 To iTotalRows
txt = XlLog.Cells(iRows, 8).Text 'Grabs appropriate comment text'
objSelection.Activate
objSelection.SelectAllEditableRanges
strpgSearch = XlLog.Cells(iRows, 2) 'Grabs appropriate Page number'
strlinSearch = XlLog.Cells(iRows, 3) 'Grabs appropriate Line number'
objSelection.ActiveWindow.Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext,
Name:=strpgSearch
objSelection.ActiveWindow.Selection.GoTo What:=wdGoToLine, Which:=wdGoToRelative,
Count:=strlinSearch
Set myRange = ActiveWindow.Selection.Range
ActiveDocument.Comments.Add Range:=myRange, Text:=txt
Next iRows
Set xlApp = Nothing
Set SaveDoc = Nothing
Set XlLog = Nothing
Set objSelection = Nothing
Set myRange = Nothing
Set wApp = Nothing
SaveDoc.Close
End Sub

How to copy a single column from word to pre-existing excel table using vba?

I have a table in word that has two columns. I want to copy only the second column into the 2nd column of my pre-existing table in excel. My 'for' loop is working but all the data is getting repeatedly stored in the same cell.How do i store in consecutive cells of the column?
Sub copyToExcel()
Dim xlapp As Excel.Application
Dim xlwb As Excel.Workbook
Dim xlsheet As Excel.Worksheet
Dim doc As Document
Dim tbl As Table
Dim lstrw As Long, lstcol As Integer
Dim tblrange As Range
Set doc = ThisDocument
Set xlapp = CreateObject("Excel.Application")
xlapp.Visible = True
Set xlwb = xlapp.Workbooks.Open("C:\Users\ankit\Downloads\challenges.xlsm")
Set xlsheet = xlwb.Worksheets("Challenge #2")
Set tbl = doc.Tables(1)
With tbl
lstrw = .Rows.Count
lstcol = .Columns.Count
For x = 2 To lstrw
Set tblrange = .Cell(x, 2).Range
tblrange.End = .Cell(lstrow, lstcol).Range.End
tblrange.Copy
xlsheet.Paste
Next x
End With
Set xlapp = Nothing
Set xlwb = Nothing
Set tblrange = Nothing
Set xlsheet = Nothing
Set doc = Nothing
End Sub

How do I get rid of my orphan MS Excel process from MS Access VBA?

I'm exporting an MS Access query to a template, doing some formatting, and then saving the template as a new name. When this is all done, I have an orphan MS Excel process that is interfering when the function is called again. I'm thinking this is either a problem with how I'm using ranges or a problem with my cleanup at the end.
Also I'm a novice coder so if anyone has any tips and tricks that I can take advantage of to make this better I'm always receptive.
Updated code after Andre's comments
Updated code after Rory's comments
Public Function OpenOrders(strSupplier As String)
'Excel file variables
Dim xlapp As Excel.Application
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Dim xlsLRow As Long
Dim xlsLCol As Long
'Access variables
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
'Set up access objects
strSQL = "SELECT * FROM qryOpenOrderReport WHERE [Supplier Cd] = '" & strSupplier & "';"
Set db = CurrentDb
Set rs = db.OpenRecordset(strSQL)
'Set up excel connection
Set xlapp = CreateObject("Excel.Application")
Set wb = xlapp.Workbooks.Open(Application.CurrentProject.Path & "\Open Order Template.xlsx")
Set ws = wb.Worksheets(1)
xlapp.Visible = True
'Make sure the form is clear
xlsLRow = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).row
xlsLCol = ws.UsedRange.Columns(ws.UsedRange.Columns.Count).Column
ws.Range("A2", ws.Cells(xlsLRow, xlsLCol)).ClearContents
'Copy recordset to worksheet
ws.Cells(2, 1).CopyFromRecordset rs
rs.Close
'Copy formats down and autofit
xlsLRow = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).row
xlsLCol = ws.UsedRange.Columns(ws.UsedRange.Columns.Count).Column
xlapp.CutCopyMode = False
ws.Range(ws.Cells(2, 1), ws.Cells(2, xlsLCol)).Copy
ws.Range(ws.Cells(3, 1), ws.Cells(xlsLRow, xlsLCol)).PasteSpecial (xlPasteFormats)
ws.UsedRange.Columns.AutoFit
'Clean up
xlapp.DisplayAlerts = False
Set ws = Nothing
wb.SaveAs Application.CurrentProject.Path & "\Open Orders\" & strSupplier & ".xlsx"
wb.Close True
Set wb = Nothing
xlapp.Quit
Set xlapp = Nothing
End Function
All of your Cells calls need to be changed to ws.Cells. That is what is causing your orphaned process.
My guess is that you still have an active reference to ws when doing the clean up, which prevents Excel from quitting.
I suggest doing it in this order:
'Clean up
xlapp.DisplayAlerts = False
Set ws = Nothing
wb.Close True, strSupplier
Set wb = Nothing
xlapp.Quit
Set xlapp = Nothing
ws.Range("A2", "XFD1048576").ClearContents seems a little radical :) - you can use .UsedRange for that.
An additional note:
After opening a recordset, you can never be in a situation where rs.EOF is False, but rs.BOF is True. So it is not necessary to test for rs.BOF.
With changing the loop to Do While, the If Not (rs.EOF And rs.BOF) Then becomes superfluous:
Set rs = db.OpenRecordset(strSQL)
Do While Not rs.EOF
' ...
rs.MoveNext
Loop
You have to be extremely specific with objects of Excel, opening them and closing in reverse order. Here's a skeleton that works:
Dim xls As Excel.Application
Dim wkb As Excel.Workbook
Dim wks As Excel.Worksheet
Dim rng As Excel.Range
Set xls = New Excel.Application
Set wkb = xls.Workbooks.Open("c:\test\workbook1.xlsx")
Set wks = wkb.Worksheets(1)
Set rng = wks.<somerange> ' Cells or whatever.
' Do stuff.
' Clean up.
Set rng = Nothing
wks.Name = "My New Name"
wkb.Close True
Set wks = Nothing
Set wkb = Nothing
xls.Quit
Set xls = Nothing
Don't ever use wkb.Sheets for a WorkSheet.

Access VBA How to add new sheets to excel?

I am running a few modules of code in access and am writing data into
Excel. When I write the first time, data gets written properly. But again
when I try, the new data is written on top of the old data. What should I do to
insert a new sheet?
My existing code is
Dim objexcel As Excel.Application
Dim wbexcel As Excel.Workbook
Dim wbExists As Boolean
Dim objSht As Excel.Worksheet
Dim objRange As Excel.Range
Set objexcel = CreateObject("excel.Application")
On Error GoTo Openwb
wbExists = False
Set wbexcel = objexcel.Workbooks.Open("C:\REPORT1.xls")
Set objSht = wbexcel.Worksheets("Sheet1")
objSht.Activate
wbExists = True
Openwb:
On Error GoTo 0
If Not wbExists Then
objexcel.Workbooks.Add
Set wbexcel = objexcel.ActiveWorkbook
Set objSht = wbexcel.Worksheets("Sheet1")
End If
I think that the following code should do what you want. It's very similar to yours, except it uses the return values from the .Add methods to get the objects you want.
Public Sub YourSub()
Dim objexcel As Excel.Application
Dim wbexcel As Excel.Workbook
Dim wbExists As Boolean
Set objexcel = CreateObject("excel.Application")
'This is a bad way of handling errors. We should'
'instead check for the file existing, having correct'
'permissions, and so on, and actually stop the process'
'if an unexpected error occurs.'
On Error GoTo Openwb
wbExists = False
Set wbexcel = objexcel.Workbooks.Open("C:\REPORT1.xls")
wbExists = True
Openwb:
On Error GoTo 0
If Not wbExists Then
Set wbexcel = objexcel.Workbooks.Add()
End If
CopyToWorkbook wbexcel
EndSub
Private Sub CopyToWorkbook(objWorkbook As Excel.Workbook)
Dim newWorksheet As Excel.Worksheet
set newWorksheet = objWorkbook.Worksheets.Add()
'Copy stuff to the worksheet here'
End Sub

Resources