I have a application that searches a .xls document. The document is 60000 rows. What I am trying to make it do is, stop searching when the result is found. Currently it all works, but it scans the rest of the 59999 rows.
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet1 As Excel.Worksheet
Dim rng As Excel.Range
Dim codeabc As String
Dim found As Boolean
Dim i As Integer
If AssociateID.Text = String.Empty Then
'popup.Close()
MsgBox("Please make sure 'Associate ID' is filled out")
Exit Sub
End If
xlApp = CreateObject("Excel.Application")
xlBook = xlApp.Workbooks.Open("G:\grps\every\People Report\HRIS Remedy Report.xls")
xlSheet1 = xlBook.Worksheets(1)
rng = xlSheet1.Range("a1:a60000")
codeabc = (AssociateID.Text)
found = False
For i = 1 To rng.Count
If rng.Cells(i).Value = codeabc Then
IDLabel.Text = AssociateID.Text
NameLabel.Text = (rng.Cells(i).offset(0, 1).value())
DepartmentLabel.Text = (rng.Cells(i).offset(0, 3).value())
PositionLabel.Text = (rng.Cells(i).offset(0, 2).value())
found = True
End If
Next i
If Not found Then
MsgBox("Associate ID: " & AssociateID.Text & " is not found. Please check the ID and try again")
AssociateID.Clear()
End If
'popup.Close()
xlBook.Close()
Fix from Plutonix that worked. Thanks!
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet1 As Excel.Worksheet
Dim rng As Excel.Range
Dim codeabc As String
Dim found As Boolean
Dim i As Integer
If AssociateID.Text = String.Empty Then
'popup.Close()
MsgBox("Please make sure 'Associate ID' is filled out")
Exit Sub
End If
xlApp = CreateObject("Excel.Application")
xlBook = xlApp.Workbooks.Open("G:\grps\every\People Report\HRIS Remedy Report.xls")
xlSheet1 = xlBook.Worksheets(1)
rng = xlSheet1.Range("a1:a60000")
codeabc = (AssociateID.Text)
found = False
For i = 1 To rng.Count
If rng.Cells(i).Value = codeabc Then
IDLabel.Text = AssociateID.Text
NameLabel.Text = (rng.Cells(i).offset(0, 1).value())
DepartmentLabel.Text = (rng.Cells(i).offset(0, 3).value())
PositionLabel.Text = (rng.Cells(i).offset(0, 2).value())
found = True
xlBook.Close()
popup.Close()
--------> Exit Sub
End If
Next i
If Not found Then
MsgBox("Associate ID: " & AssociateID.Text & " is not found. Please check the ID and try again")
AssociateID.Clear()
End If
'popup.Close()
xlBook.Close()
Related
Sources:
Private Sub toEditDataOnReportCell(ByVal passedData As String)
Dim monthlyReportFilePath As String = "./Report/Example.xlsx"
Dim oExcel As Object
Dim oBook As Object
Dim oSheet As Object
'Start a new workbook in Excel
oExcel = CreateObject("Excel.Application")
oBook = oExcel.Workbooks.Open(monthlyReportFilePath)
'Set which worksheet tobe modified
oSheet = oBook.Worksheets(1)
'This will find the lastRow in the sheet
'Dim lastRow As Integer = 7
Dim ETLastRow As Integer = oSheet.usedrange.rows.count
'This is next emptyRow in the sheet
Dim ETemptyRow As Integer = ETLastRow + 1
'edit last empty row val on column 8
Dim columnToMod As Integer = 8
oSheet.Cells(ETemptyRow, columnToMod).value = passedData
ETLastRow = oSheet.usedrange.rows.count
ETemptyRow = ETLastRow + 1
'This will not prompt the user to overwrite the excel sheet
oExcel.DisplayAlerts = False
oBook.Save()
oBook.Close()
oExcel.Quit()
TextBox12.AppendText("Sucess!!!" + vbCrLf + vbCrLf)
End Sub
Giving wrong last row, if in excel doc already have a table with formula in it.
Output Preview:
Targeting In Cell Range (H8:H38)
[1]: https://i.stack.imgur.com/D4RT5.png
But Output In Cell Range (H40:H)
[2]: https://i.stack.imgur.com/0wufs.png
Hehehe, i found the solutions,
Thanks to #StoriKnow & his answer there:
Here is my latest sources:
Private Sub toEditDataOnReportCell(ByVal passedData As String)
Dim monthlyReportFilePath As String = "./Report/Example.xlsx"
Dim oExcel As New Object
Dim oBook As New Object
Dim oSheet As New Object
oExcel = CreateObject("Excel.Application")
oBook = oExcel.Workbooks.Open(monthlyReportFilePath)
oSheet = oBook.Worksheets(1)
Try
Dim sourceCol As Integer, rowCount As Integer, currentRow As Integer
Dim currentRowValue As String
sourceCol = 8 'column H has a value of 8
rowCount = oSheet.Cells(oSheet.Rows.Count, sourceCol).End(Excel.XlDirection.xlUp).Row
'for every row, find the first blank cell and select it
For currentRow = 8 To rowCount
currentRowValue = oSheet.Cells(currentRow, sourceCol).Value
If (currentRowValue Is Nothing) Or (currentRowValue = "") Then
'oSheet.Cells(currentRow, sourceCol).Select
Dim preview As String = currentRow
TextBox12.AppendText(preview + " ")
oSheet.Cells(currentRow, sourceCol).Select
oSheet.Cells(currentRow, sourceCol).value = passedData
Exit Try
End If
Next
Finally
''' DO NOTHING
End Try
''This will not prompt the user to overwrite the excel sheet
oExcel.DisplayAlerts = False
oBook.Save()
oBook.Close()
oExcel.Quit()
end Sub
Output that achived:
I want to Export large data stock from Access to Excel. I'm doing that with a form.
My code with "DoCmd.TransferSpreadsheet acExport..." works normally, but the program breaks off because of the large data stock.
Perhaps with queries I can solve this Problem, or what do you think?
I am thankful for each tip! =)
you can you use below code: this will copy the datesheet view in your form and copy paste it in to one excel file .For this you just drag one sub form control from tool box in to your form and set the property of this sub form's source data as your query name and replace the sub form name in the code
Private Sub Command48_Click()
On Error GoTo Command13_Click_Err
Me.subformName.SetFocus
'DoCmd.GoToControl "Policy Ref"
DoCmd.RunCommand acCmdSelectAllRecords
DoCmd.RunCommand acCmdCopy
Dim xlapp As Excel.Application
Set xlapp = CreateObject("Excel.Application")
With xlapp
.Workbooks.Add
.ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:= _
False
.Cells.Select
.Cells.EntireColumn.AutoFit
.Visible = True
.Range("a1").Select
End With
Command13_Click_Exit:
Exit Sub
Command13_Click_Err:
MsgBox Error$
Resume Command13_Click_Exit
End sub
'=======================
you can you use below code: this will copy the datesheet view in your form and copy paste it in to one excel file .For this you just drag one sub form control from tool box in to your form and set the property of this sub form's source data as your query name and replace the sub form name in the code
Private Sub Command48_Click()
On Error GoTo Command13_Click_Err
Me.subformName.SetFocus
'DoCmd.GoToControl "Policy Ref"
DoCmd.RunCommand acCmdSelectAllRecords
DoCmd.RunCommand acCmdCopy
Dim xlapp As Excel.Application
Set xlapp = CreateObject("Excel.Application")
With xlapp
.Workbooks.Add
.ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:= _
False
.Cells.Select
.Cells.EntireColumn.AutoFit
.Visible = True
.Range("a1").Select
End With
Command13_Click_Exit:
Exit Sub
Command13_Click_Err:
MsgBox Error$
Resume Command13_Click_Exit
End sub
'''PPT
Sub pptExoprort()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationAutomatic
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim PPApp As PowerPoint.Application
Dim PPPres As PowerPoint.Presentation
Dim slideNum As Integer
Dim chartName As String
Dim tableName As String
Dim PPTCount As Integer
Dim PPSlideCount As Long
Dim oPPTShape As PowerPoint.Shape
Dim ShpNm As String
Dim ShtNm As String
Dim NewSlide As String
Dim myChart As PowerPoint.Chart
Dim wb As Workbook
Dim rngOp As Range
Dim ro As Range
Dim p As Integer
Dim v, v1, v2, v3, Vtot, VcaGr
Dim ws As Worksheet
Dim ch
Dim w As Worksheet
Dim x, pArr
Dim rN As String
Dim rt As String
Dim ax
Dim yTbN As String
'Call InitializeGlobal
''start year offset
prodSel = shtSet.Range("rSelProd")
x = shtSet.Range("rngMap").Value
pArr = fretPrVal(x, prodSel)
TY = 11 'number of years in chart
ThisWorkbook.Activate
Set w = ActiveSheet
Set PPApp = GetObject("", "Powerpoint.Application") '******************
PPTCount = PPApp.Presentations.Count
If PPTCount = 0 Then
MsgBox ("Please open a PPT to export the Charts!")
Exit Sub
End If
Set PPPres = PPApp.ActivePresentation '******************
For j = 0 To UBound(pArr)
If j = 0 Then
rN = "janport"
slideNum = 3
yTbN = "runport"
Else
rN = "janprod" & j
slideNum = 3 + j
yTbN = "runprod" & j
End If
chartName = "chtSalesPort"
Set PPSlide = PPPres.Slides(slideNum) '**************
PPApp.ActiveWindow.View.GotoSlide PPSlide.SlideIndex
Set myChart = PPSlide.Shapes(chartName).Chart '******************
myChart.ChartData.Activate '********************
Set wb = myChart.ChartData.Workbook '***********
Set ws = wb.Worksheets(1) '**************
Set rngOp = w.Range(rN).Offset(0, 1).Resize(12, 6)
Set ro = rngOp
' v1 = ro.Offset(1, 22).Resize(Lc, 1)
'ws.ListObjects("Table1").Resize Range("$A$1:$B$" & Ty + 1)
'ws.ListObjects("Table1").Resize Range("$A$1:$" & Chr(Lc + 1 + 64) & "$" & Ty + 1)
ws.Range("B2:g13").ClearContents '***********
rngOp.Copy '**********
ws.Range("B2:g13").PasteSpecial xlPasteValues '******************
End Sub
Sub Picture62_Click()
Dim charNamel As String
Dim leftm As Integer
Dim toptm As Integer
charNamel = "Chart 1"
leftm = 35
toptm = 180
Call chartposition(leftm, toptm, charNamel)
End Sub
Sub chartposition(leftm, toptm, charNamel)
ActiveSheet.ChartObjects(charNamel).Activate
'First we declare the variables we will be using
Dim newPowerPoint As PowerPoint.Application
Dim activeSlide As PowerPoint.Slide
Dim cht As Excel.ChartObject
Dim activslidenumber As Integer
'Look for existing instance
On Error Resume Next
Set newPowerPoint = GetObject(, "PowerPoint.Application")
On Error GoTo 0
'Let's create a new PowerPoint
If newPowerPoint Is Nothing Then
Set newPowerPoint = New PowerPoint.Application
End If
'Make a presentation in PowerPoint
' If newPowerPoint.Presentations.Count = 0 Then
' newPowerPoint.Presentations.Add
' End If
'Show the PowerPoint
newPowerPoint.Visible = True
On Error GoTo endd:
activslidenumber = Str(GetActiveSlide(newPowerPoint.ActiveWindow).SlideIndex)
Set activeSlide = newPowerPoint.ActivePresentation.Slides(activslidenumber)
ActiveChart.ChartArea.Copy
On Error GoTo endddd:
activeSlide.Shapes.PasteSpecial(DataType:=ppPasteDefault).Select
'activeSlide.Shapes.PasteSpecial(DataType:=ppPasteMetafilePicture).Select
'activeSlide.Shapes.PasteSpecial(DataType:=ppPasteOLEObject, DisplayAsIcon:=msoFalse).Select
endddd:
newPowerPoint.ActiveWindow.Selection.ShapeRange.Left = leftm
newPowerPoint.ActiveWindow.Selection.ShapeRange.Top = toptm
GoTo enddddd:
endd:
MsgBox ("Please keep your PPT file opened")
enddddd:
End Sub
Can anyone point out what is causing the excel process to remain open after my code finishes?
I've researched everything on this topic and the main point seems to be to avoid 3 dots with excel interop, but I believe I have done that and I still can't see where I'm going wrong.
my process is to copy the datagridview to the clipboard and then paste it in a newly created excel file, save it, close excel, and then give the user an option to open the file.
Two scenarios. First, when I run through the code and DON'T open the excel file it leaves the process open. Second, if I open the workbook and then close the workbook it doesn't leave a process running. I don't understand the difference because the opening of the workbook happens after I try to close and release all references to excel.
Private Sub CopyDGVtoClipBoard()
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
Me.DataGridView1.RowHeadersVisible = False
Me.DataGridView1.SelectAll()
Dim dataObj As DataObject = Me.DataGridView1.GetClipboardContent
If dataObj IsNot Nothing Then
Clipboard.SetDataObject(dataObj)
End If
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithAutoHeaderText
Me.DataGridView1.RowHeadersVisible = True
Me.DataGridView1.ClearSelection()
End Sub
Private Sub ExportToExcel()
If Me.DataGridView1.Rows.Count < 1 Then Exit Sub
CopyDGVtoClipBoard()
SaveFileDialog1.Filter = "Excel File|*.xlsx"
SaveFileDialog1.Title = "Save In"
SaveFileDialog1.FileName = "Generic name"
If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
If SaveFileDialog1.FileName <> "" Then
Dim xlExcel As excel.Application
Dim xlWorkBooks As excel.Workbooks
Dim xlWorkBook As excel.Workbook
Dim xlWorkSheet As excel.Worksheet
Dim CR As excel.Range
Dim misValue As Object = System.Reflection.Missing.Value
xlExcel = New excel.Application
xlExcel.Visible = True
xlWorkBooks = xlExcel.Workbooks
xlWorkBook = xlWorkBooks.Add(misValue)
xlWorkBook.Application.DisplayAlerts = False
xlWorkSheet = xlWorkBook.ActiveSheet
CR = xlWorkSheet.Cells(1, 1)
CR.Select()
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
xlWorkBook.SaveAs(SaveFileDialog1.FileName())
xlWorkBook.Close(False)
misValue = Nothing
ReleaseExcel(CR)
ReleaseExcel(xlWorkSheet)
ReleaseExcel(xlWorkBook)
ReleaseExcel(xlWorkBooks)
xlExcel.Quit()
ReleaseExcel(xlExcel)
Dim OpenCheck As MsgBoxResult = MsgBox("Would you like to open the file?", MsgBoxStyle.YesNo, "Open File")
Dim fPath As String = SaveFileDialog1.FileName
If OpenCheck = MsgBoxResult.Yes Then
Process.Start(fPath)
End If
End If
End If
Private Sub ReleaseExcel(ByVal O As Object)
Do While System.Runtime.InteropServices.Marshal.ReleaseComObject(O) >= 0
System.Runtime.InteropServices.Marshal.ReleaseComObject(O)
Loop
O = Nothing
End Sub
I've narrowed the issue down to the below code. If I do everything except specifying a range and adding data it'll close and end the process but as soon as I reference CR = xlWorkSheet.Cells(1,1) it hangs a process
CR = xlWorkSheet.Cells(1, 1)
CR.Select()
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
Edit
So I compared my code vs. what Karen posted and made some slight adjustments to my code (full code plus changes listed below), but for some reason it works and doesn't leave a process open! Not sure how, but I'll take it.
Private Sub CopyDGVtoClipBoard()
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
Me.DataGridView1.RowHeadersVisible = False
Me.DataGridView1.SelectAll()
Dim dataObj As DataObject = Me.DataGridView1.GetClipboardContent
If dataObj IsNot Nothing Then
Clipboard.SetDataObject(dataObj)
End If
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithAutoHeaderText
Me.DataGridView1.RowHeadersVisible = True
Me.DataGridView1.ClearSelection()
End Sub
Private Sub ExportToExcel()
If Me.DataGridView1.Rows.Count < 1 Then Exit Sub
CopyDGVtoClipBoard()
Dim DateCon As DateTime = DateTime.ParseExact(Today.ToShortDateString, "M/d/yyyy", Nothing)
SaveFileDialog1.Filter = "Excel File|*.xlsx"
SaveFileDialog1.Title = "Save In"
SaveFileDialog1.FileName = "Generic Name"
If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
If SaveFileDialog1.FileName <> "" Then
Dim xlExcel As excel.Application = Nothing
Dim xlWorkBooks As excel.Workbooks = Nothing
Dim xlWorkBook As excel.Workbook = Nothing
Dim xlWorkSheet As excel.Worksheet = Nothing
Dim CR As excel.Range = Nothing
Dim misValue As Object = System.Reflection.Missing.Value
xlExcel = New excel.Application
xlExcel.Visible = False
xlExcel.DisplayAlerts = False
xlWorkBooks = xlExcel.Workbooks
xlWorkBook = xlWorkBooks.Add(misValue)
xlWorkSheet = xlWorkBook.ActiveSheet
CR = xlWorkSheet.Range("A1")
CR.PasteSpecial(excel.XlPasteType.xlPasteAll)
CR.Select()
xlWorkBook.SaveAs(SaveFileDialog1.FileName)
Clipboard.Clear()
ReleaseExcel(CR)
CR = Nothing
ReleaseExcel(xlWorkSheet)
xlWorkSheet = Nothing
xlWorkBook.Close(False)
ReleaseExcel(xlWorkBook)
xlWorkBook = Nothing
ReleaseExcel(xlWorkBooks)
xlWorkBooks = Nothing
xlExcel.Quit()
ReleaseExcel(xlExcel)
xlExcel = Nothing
Dim OpenCheck As MsgBoxResult = MsgBox("Would you like to open the file?", MsgBoxStyle.YesNo, "Open File")
Dim fPath As String = SaveFileDialog1.FileName
If OpenCheck = MsgBoxResult.Yes Then
Process.Start(fPath)
End If
End If
End If
End Sub
Private Sub ReleaseExcel(ByVal O As Object)
Try
Do Until System.Runtime.InteropServices.Marshal.FinalReleaseComObject(O) = 0
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(O)
Loop
Catch ex As Exception
Finally
GC.Collect()
GC.WaitForPendingFinalizers()
End Try
End Sub
The following goes along with using only two dots. After the work is done excel is properly disposed of.
Option Strict On
Option Infer Off
Imports Excel = Microsoft.Office.Interop.Excel
Imports Microsoft.Office
Imports System.Runtime.InteropServices
Module Demo1
Public Sub DoPaste()
Dim FileName As String = IO.Path.Combine(Application.StartupPath, "SomeFile.xlsx")
Dim SheetName As String = "Sheet1"
Dim Proceed As Boolean = False
Dim xlApp As Excel.Application = Nothing
Dim xlWorkBooks As Excel.Workbooks = Nothing
Dim xlWorkBook As Excel.Workbook = Nothing
Dim xlWorkSheet As Excel.Worksheet = Nothing
Dim xlWorkSheets As Excel.Sheets = Nothing
Dim xlCells As Excel.Range = Nothing
xlApp = New Excel.Application
xlApp.DisplayAlerts = False
xlWorkBooks = xlApp.Workbooks
xlWorkBook = xlWorkBooks.Open(FileName)
xlApp.Visible = False
xlWorkSheets = xlWorkBook.Sheets
For x As Integer = 1 To xlWorkSheets.Count
xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)
If xlWorkSheet.Name = SheetName Then
Dim xlRange1 As Excel.Range = Nothing
xlRange1 = xlWorkSheet.Range("A1:B6")
xlRange1.Select()
xlRange1.Copy()
Dim xlDestination As Excel.Range = Nothing
xlDestination = xlWorkSheet.Range("C1:D6")
xlDestination.PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone)
Marshal.FinalReleaseComObject(xlDestination)
xlDestination = Nothing
Marshal.FinalReleaseComObject(xlRange1)
xlRange1 = Nothing
xlWorkSheet.SaveAs(FileName)
Marshal.FinalReleaseComObject(xlWorkSheet)
xlWorkSheet = Nothing
Exit For
End If
Next
xlWorkBook.Close()
xlApp.UserControl = True
xlApp.Quit()
ReleaseComObject(xlCells)
ReleaseComObject(xlWorkSheets)
ReleaseComObject(xlWorkSheet)
ReleaseComObject(xlWorkBook)
ReleaseComObject(xlWorkBooks)
ReleaseComObject(xlApp)
End Sub
Private Sub ReleaseComObject(ByVal obj As Object)
Try
If obj IsNot Nothing Then
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
End If
Catch ex As Exception
obj = Nothing
End Try
End Sub
End Module
Goal
Import about 100+ lines of data into a worksheet. Quickly.
Current Problem
The Excel file isn't very large (not even 1MB). Although, we use this Excel file to communicate with SolidEdge which makes it very heavy.
At the moment, it takes about 60 seconds to populate the 100 lines of data. Don't get me wrong, that isn't very long. Whereas I tested it with a new and empty Excel file and it took less than 1 second to populate the data.
Code
Here's my code incase I did something stupid in there:
Private Sub PopulateExcel()
Dim xlApp As Excel.Application = Nothing
Dim xlWorkBooks As Excel.Workbooks = Nothing
Dim xlWorkBook As Excel.Workbook = Nothing
Dim xlWorkSheet As Excel.Worksheet = Nothing
Dim xlWorkSheets As Excel.Sheets = Nothing
Dim Proceed As Boolean = False
Dim RowIndex As Integer = 2
Dim counter As Integer = 0
xlApp = CType(Marshal.GetActiveObject("Excel.Application"), Excel.Application)
xlWorkBooks = xlApp.Workbooks
For Each wb As Excel.Workbook In xlWorkBooks
If wb.Name.Contains("301-AAAA-00X") Then
xlWorkBook = wb
xlWorkSheets = xlWorkBook.Sheets
Exit For
End If
Next
If xlWorkSheets IsNot Nothing Then
For x As Integer = 1 To xlWorkSheets.Count
xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)
If xlWorkSheet.Name = "ImportSheet" Then
Proceed = True
Exit For
End If
Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkSheet)
xlWorkSheet = Nothing
Next
End If
If Proceed Then
tspbProgress.Value = 0
tspbProgress.Maximum = dic_Vars.Count
tspbProgress.Visible = True
For Each key As KeyValuePair(Of String, String) In dic_Vars 'Contains all my the data
tsslStatus.Text = "Populating Excel: " & key.Key & " | " & key.Value
xlWorkSheet.Cells(RowIndex, 2).value = key.Key
xlWorkSheet.Cells(RowIndex, 3).value = key.Value
RowIndex += 1
IncProg()
Next
tspbProgress.Visible = False
ReleaseComObject(xlWorkSheets)
ReleaseComObject(xlWorkSheet)
ReleaseComObject(xlWorkBook)
ReleaseComObject(xlWorkBooks)
ReleaseComObject(xlApp)
End If
End Sub
Private Sub ReleaseComObject(ByRef obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
End Try
End Sub
Conclusion
I was thinking about creating a new Excel file, importing the data there, and just doing a copy / paste to the real Excel file that we use.
Any suggestions?
Good thank you to Byron Wall who helped me find the answer. I now input my data using an array instead of iterating through each cell.
I create my array and populate it depending on how large my dictionary of variables is. I then create a new range using the Resize() method seen below.
Once that's done, everything is populated in an instant!
Dim arrNames(,) As String = New String(AscW(ChrW(dic_Vars.Count)), 1) {}
Dim arrValues(,) As String = New String(AscW(ChrW(dic_Vars.Count)), 1) {}
Dim i As Integer = 0
For Each key As KeyValuePair(Of String, String) In dic_Vars
arrNames(i, 0) = key.Key
arrValues(i, 0) = key.Value
i += 1
Next
If Proceed Then
Dim r As Microsoft.Office.Interop.Excel.Range = xlWorkSheet.Range("B2").Resize(arrNames.GetLength(0))
Dim r2 As Microsoft.Office.Interop.Excel.Range = xlWorkSheet.Range("C2").Resize(arrValues.GetLength(0))
r.Value2 = arrNames
r2.Value2 = arrValues
ReleaseComObject(xlWorkSheets)
ReleaseComObject(xlWorkSheet)
ReleaseComObject(xlWorkBook)
ReleaseComObject(xlWorkBooks)
ReleaseComObject(xlApp)
End If
I am attempting to log (1. what slide and 2. the time) to a spreadsheet each time a slide is viewed in presentation mode. I don't want to have the spreadsheet open when I do this and I want it to save automatically. I've been screwing around with it for a few hours now, and I've had varying success. I can't seem to get it to work as intended.
Here's the code I've crammed together so far:
Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)
Dim appExcel As Excel.Application
Dim wkb As Excel.Workbook
Dim wks As Excel.Worksheet
Dim strSheet As String
Dim strPath As String
Dim curentSlide As Integer
Dim timez As Date
Dim z As Integer
strSheet = "test.xlsx"
strPath = "C:\PPToutput\"
strSheet = strPath & strSheet
Dim counter As Integer
counter = 0
counter = counter + 1
currentslide = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
timez = Now()
If Not IsNull(appExcel) And counter < 2 Then
Set appExcel = CreateObject("Excel.Application")
appExcel.Application.DisplayAlerts = False
appExcel.Workbooks.Open (strSheet)
Set wkb = appExcel.ActiveWorkbook
Set wks = wkb.Sheets(1)
wks.Activate
End If
appExcel.Application.Visible = True
Range("A" & Rows.Count).End(xlUp).Offset(1).Value = "Slide " & currentslide
Range("B" & Rows.Count).End(xlUp).Offset(1).Value = timez
wks.Columns.AutoFit
wkb.SaveAs
Set appExcel = Nothing
appExcel.Workbooks.Close
appExcel.Quit
Set appExcel = Nothing
End Sub
I haven't tried the code out, but something I noticed is that this line:
appExcel.Application.Visible = False
comes after the excel program does stuff. I would imagine the workbook opening would be visible because that happens before this line.
Also, I don't see where you're telling the OnSlideShowPageChange sub anything about the workbook you created in the SlideShowBegin sub. You're telling it to do something with a range, which is not the one you declared earlier. So, it thinks you're talking about some range in the powerpoint. Do powerpoints even have ranges?
The other mistake is that you set all of your public declarations to nothing. Once you try to call them again, you're calling nothing. It's still a good idea to do that in your error handler, but not as a normal part of the process.
Look at the [untested] changes I made and see if they make sense:
Public appExcel As Excel.Application
Public wkb As Excel.Workbook
Public wks As Excel.Worksheet
Public rng As Excel.Range
Public strSheet As String
Public strPath As String
Public intRowCounter As Integer
Public intColumnCounter As Integer
Public itm As Object
Sub SlideShowBegin()
On Error GoTo ErrHandler
strSheet = "test.xlsx"
strPath = "C:\PPToutput\"
strSheet = strPath & strSheet
Debug.Print strSheet
'Select export folder
Dim curentSlide As Integer
Dim timez As Date
Dim z As Integer
Dim placeholder1 As String
Dim placeholder2 As String
currentslide = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
timez = Now()
Set appExcel = CreateObject("Excel.Application")
appExcel.Application.Visible = False
appExcel.Workbooks.Open (strSheet)
Set wkb = appExcel.ActiveWorkbook
Set wks = wkb.Sheets(1)
wks.Activate
wks.Range("A1").Value = "Current Slide"
wks.Range("B1").Value = "Time"
Exit Sub
ErrHandler:
If Err.Number = 1004 Then
MsgBox strSheet & " doesn't exist", vbOKOnly, _
"Error"
Else
MsgBox Err.Number & "; Description: ", vbOKOnly, _
"Error"
End If
Set appExcel = Nothing
Set wkb = Nothing
Set wks = Nothing
Set rng = Nothing
Set msg = Nothing
Set nms = Nothing
Set fld = Nothing
Set itm = Nothing
End Sub
Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)
Dim curentSlide As Integer
Dim timez As Date
Dim z As Integer
Dim placeholder1 As String
Dim placeholder2 As String
currentslide = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
timez = Now()
wks.Range("A" & Rows.Count).End(xlUp).Offset(1).Value = "Slide " & currentslide
wks.Range("B" & Rows.Count).End(xlUp).Offset(1).Value = timez
wks.Columns.AutoFit
wkb.Save
If SSW.View.CurrentShowPosition = _
SSW.Presentation.SlideShowSettings.EndingSlide Then
wkb.Save
wkb.Close
End If
End Sub
Sub SlideShowEnd()
wkb.Save
wkb.Close
End Sub
I rearranged your code a bit so that the initialization only occurs once during the slide show. I added another procedure to close Excel once the slide show has ended.
Private appExcel As Excel.Application
Private wkb As Excel.Workbook
Private wks As Excel.Worksheet
Private counter As Integer
Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)
' initialization
Dim strSheet As String
Dim strPath As String
strSheet = "test.xlsx"
strPath = "C:\PPToutput\"
strSheet = strPath & strSheet
Debug.Print strSheet, appExcel Is Nothing
If appExcel Is Nothing Then
Set appExcel = CreateObject("Excel.Application")
appExcel.Application.DisplayAlerts = False
appExcel.WindowState = xlMinimized
appExcel.Visible = True
Set wkb = appExcel.Workbooks.Open(strSheet)
Set wks = wkb.Sheets(1)
counter = wks.UsedRange.Rows.Count - 1
End If
' make log entry
Dim currentSlide As Integer
currentSlide = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
counter = counter + 1
wks.Range("A" & counter).Value = "Slide " & currentSlide
wks.Range("B" & counter).Value = Now()
End Sub
Sub OnSlideShowTerminate(ByVal Wn As SlideShowWindow)
If Not appExcel Is Nothing Then
wks.Columns.AutoFit
appExcel.WindowState = xlNormal
wkb.Close True
appExcel.Quit
End If
Set appExcel = Nothing
End Sub
If it were my code, I'd also factor out the initialization code and put it in its own procedure so that the OnSlideShowPageChange procedure focused on the logging of the slide changes.