I had this code working a few days ago, but forgot to save the working copy. It took me 4 weeks just to find this answer and would not like to take that much time again, so...
Everything here works, except the objWorkBook lines, which return the error:
"Variable 'objWorkBook' is used before it has been assigned a value. A null reference exception could result at runtime."
Any suggestions?
Dim objExcel As Excel.Application = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
Dim objWorkBook As Excel.Workbook
Dim totalWorkBooks As Integer = objExcel.Workbooks.Count
MsgBox(totalWorkBooks & " is Number of Open Workbooks")
Dim ActiveBookIndex As Integer = objExcel.ActiveWindow.Index
MsgBox(ActiveBookIndex & " is Active Window Index")
Dim FullName As String = objWorkBook.FullName
MsgBox(FullName & " is FullName")
Dim OnlyName As String = objWorkBook.Name
MsgBox(OnlyName & " is Name without the Path")
I forgot what Value I had assigned.
My objective is to compare an open Excel Workbook name with one in a known location so that if they match, my program can proceed. I need the code above so I can compare it to the following code in an If-Then so that my program can proceed.
Dim dir As String = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
Dim FullFileName As String = dir & "\My_File_Name.xlsx"
On a positive note, I pieced together A solution, even though it's not the answer I was looking for....
Dim p() As Process = System.Diagnostics.Process.GetProcessesByName("Excel")
Dim Title As String = p(0).MainWindowTitle
Dim dir As String = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
Dim FullFileName As String = dir & "\" & Replace(Title, "Microsoft Excel - ", "") & ".xlsx"
MsgBox(dir)
MsgBox(Title)
MsgBox(FullFileName)
This will work for now, but I would like to solve it the other way.
Change the line
Dim objWorkBook As Excel.Workbook
to
Dim objWorkBook As Excel.Workbook = Nothing
Also your objWorkBook object is not assigned to anything before you are trying to use it in the line Dim FullName As String = objWorkBook.FullName
Is this what you are trying?
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim objExcel As Excel.Application = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
Dim objWorkBook As Excel.Workbook
Dim totalWorkBooks As Integer = objExcel.Workbooks.Count
MsgBox (totalWorkBooks & " is Number of Open Workbooks")
Dim ActiveBookIndex As Integer = objExcel.ActiveWindow.Index
MsgBox (ActiveBookIndex & " is Active Window Index")
'~~> Set the workbook to say first workbook.
'~~> You can use a loop here as well to loop through
'~~> the workbooks count
objWorkBook = objExcel.Workbooks(1)
Dim FullName As String = objWorkBook.FullName
MsgBox (FullName & " is FullName")
Dim OnlyName As String = objWorkBook.Name
MsgBox (OnlyName & " is Name without the Path")
'
'~~> Rest of the code
'
End Sub
End Class
EDIT: Followup from comments
But let's say I have 9 Workbooks already open, how do I get me app to index, manipulate, switch between them... without knowing the Full Path and File Names ahead of time?
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim objExcel As Excel.Application = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
Dim objWorkBook As Excel.Workbook = Nothing
Dim FullName As String = ""
Dim OnlyName As String = ""
Dim totalWorkBooks As Integer = objExcel.Workbooks.Count
MsgBox (totalWorkBooks & " is Number of Open Workbooks")
For i As Integer = 1 To totalWorkBooks
objWorkBook = objExcel.Workbooks(i)
With objWorkBook
FullName = .FullName
OnlyName = .Name
MessageBox.Show (FullName & " is FullName and " & OnlyName & " is Name without the Path")
'
'~~> Rest of the code here to manipulate the workbook. For example
' objWorkBook.Sheets(1).Range("A1").Value = "Blah Blah"
'
End With
Next i
releaseObject (objExcel)
releaseObject (objWorkBook)
End Sub
'~~> Release the objects
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject (obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class
Related
I am writing a program that is supposed to merge several word documents into one keeping the formatting of each document. After some research on the web wrote a version that is supposed to work, which is the following:
Public Sub processmodulestest(ByVal id As Integer)
Dim oMissing = System.Reflection.Missing.Value
Dim oFalse = False
Dim oTrue = True
Dim fileDirectory = "C:\<file-path>\MOD-TEST\"
Dim wrdApp As New Word.Application
Dim destDoc As Word.Document 'destination doc
Dim docfile As Word.Document 'tmp doc to paste
destDoc = wrdApp.Documents.Add
'docNew.PageSetup.TopMargin = wrdApp.InchesToPoints(1.0F)
'docNew.PageSetup.BottomMargin = wrdApp.InchesToPoints(0.0F)
Dim wordFiles() As String = Directory.GetFiles(fileDirectory, "*.doc")
wrdApp.Options.Pagination = False
wrdApp.ActiveWindow.View.ShowAll = True
For Each el As String In wordFiles
docfile = wrdApp.Documents.Open(el, False, False)
wrdApp.Selection.WholeStory()
wrdApp.Selection.Copy()
wrdApp.ActiveWindow.Close(Word.WdSaveOptions.wdDoNotSaveChanges)
destDoc.Activate()
wrdApp.Selection.PasteAndFormat(Word.WdRecoveryType.wdFormatOriginalFormatting)
wrdApp.Selection.InsertBreak(Word.WdBreakType.wdPageBreak)
Next
wrdApp.Visible = True
End Sub
I get the following Error:
An unhandled exception of type'System.Runtime.InteropServices.COMException'
HRESULT: 0x80010108 (RPC_E_DISCONNECTED)) The object invoked has disconnected from its clients.
referring to the following line:
destDoc.Activate()
I read that this should be because the code uses an unqualified method on an Office instance that has been ended, but i can't understand how to fix it
I'm not sure how to do it in VB.NET, but the VBA code below will merge all Word documents into one single consolidated Word document.
Appending multiple Word docs into a single Word doc
Sub Foo()
Dim i As Long
Dim MyName As String, MyPath As String
Application.ScreenUpdating = False
Documents.Add
MyPath = "C:\Documents and Settings\Excel\Desktop\Word Files\" ' <= change this as necessary
MyName = Dir$(MyPath & "*.doc") ' not *.* if you just want doc files
Do While MyName <> ""
If InStr(MyName, "~") = 0 Then
Selection.InsertFile _
FileName:="""" & MyPath & MyName & """", _
ConfirmConversions:=False, Link:=False, _
Attachment:=False
Selection.InsertBreak Type:=wdPageBreak
End If
MyName = Dir ' gets the next doc file in the directory
Loop
End Sub
Private Sub Createbutton_Click(sender As Object, e As EventArgs) Handles Create.Click
Dim MyPassword As String = "Password"
Dim oItem As Object
Dim OffS As Integer
Dim MsExcel As Excel.Application
Dim Wb As Excel.Workbook
MsExcel = CreateObject("Excel.Application")
'ASPTS is my project name and Default is a folder i created
Wb = MsExcel.Workbooks.Add("..\\ASPTS\ASPTS\Default\football.xlsm")
OffS = 0
For Each oItem In TeamListBox.Items
Wb.Sheets(1).Range("A2").Offset(OffS, 0).Value = oItem
OffS = OffS + 1
Next oItem
FSaveFileDialog.Filter = "Excel Files (*.xlsm)|*.xslsm"
Wb.SaveAs(Filename:="..\\ASPTS\ASPTS\Football\" & TextBox1.Text & ".xlsm", FileFormat:=52, Password:=MyPassword,
WriteResPassword:=MyPassword, ReadOnlyRecommended:=False, CreateBackup:=False)
Wb.Close()
End Sub
If I change the path like this
("C:\Users\UserName\Desktop\ASPTS\ASPTS\Default\football.xlsm")
it works fine but I don't want to specify any drive in folder path because my project should be able to run in other drives and other by users too.
In the following code, I want to access ExcelWorkbook1 declared in Sub OpenExcel in Sub SelectRangeOfCells. Please help me with the same.
Public Sub OpenExcel(ByVal Path As String, ByVal Filename As String)
Dim xlApp As Excel.Application = New Microsoft.Office.Interop.Excel.Application()
xlApp.Visible = True
If xlApp Is Nothing Then
MessageBox.Show("Excel is not properly installed!!")
End If
Dim MyFile As String = Dir$(Path + "\" + Filename)
If MyFile = Filename Then
Dim ExcelWorkbook1 As Workbook = xlApp.Workbooks.Open(Path + "\" + Filename)
Else
MessageBox.Show("Excel not found!")
End If
End Sub
Public Sub SelectRangeOfCells(ByVal Sheet As String, ByVal Range As String)
ExcelWorkbook1.Worksheets(Sheet).activate
End Sub
This shows error in SelectRangeOfCells Sub that ExcelWorkbook1 is not declared.
This is kinda basic.
Of course, you cannot access ExcelWorkbook1 from another sub because it is declared locally in the OpenExcel sub.
To access ExceWorkBook1 using both subs, you must declare it outside of those two subs.
Dim ExcelWorkbook1 As Workbook 'put this here
Public Sub OpenExcel(ByVal Path As String, ByVal Filename As String)
Dim xlApp As Excel.Application = New Microsoft.Office.Interop.Excel.Application()
xlApp.Visible = True
If xlApp Is Nothing Then
MessageBox.Show("Excel is not properly installed!!")
End If
Dim MyFile As String = Dir$(Path + "\" + Filename)
If MyFile = Filename Then
ExcelWorkbook1 = xlApp.Workbooks.Open(Path + "\" + Filename) 'The declaration here is moved outside of the sub, granting access to the other subs
Else
MessageBox.Show("Excel not found!")
End If
End Sub
You have to declare ExcelWorkbook1 as a class property then use it in yours methods:
Property ExcelWorkbook1 As Workbook
Public Sub OpenExcel(ByVal Path As String, ByVal Filename As String)
Dim xlApp As Excel.Application = New Microsoft.Office.Interop.Excel.Application()
xlApp.Visible = True
If xlApp Is Nothing Then
MessageBox.Show("Excel is not properly installed!!")
End If
Dim MyFile As String = Dir$(Path + "\" + Filename)
If MyFile = Filename Then
ExcelWorkbook1 = xlApp.Workbooks.Open(Path + "\" + Filename)
Else
MessageBox.Show("Excel not found!")
End If
End Sub
Public Sub SelectRangeOfCells(ByVal Sheet As String, ByVal Range As String)
ExcelWorkbook1.Worksheets(Sheet).activate
End Sub
More about properties in VB.NET you can learn from MSDN
I have 750 Excel files that I want to
clean by deleting columns of data that have a heading with an asterisk,
then take some of that data and put it in a new workbook worksheet, and other data into the same workbook worksheet, and some other data into a second new workbook.
I created a WPF project in Visual Studio 2015 with a little dialog box with 2 radio buttons for
clean data,
produce new files.
This is my VB code:
Class MainWindow
Dim wb As Microsoft.Office.Interop.Excel._Workbook
Dim ws As Microsoft.Office.Interop.Excel._Worksheet
Dim iCol As Integer
Dim strName As String
Dim iIndex As Integer
Dim strPath As String
Dim strFile As String
Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
If cleanRadioButton.IsChecked = True Then
strPath = "c:\test\old\"
strFile = Dir(strPath & "*.csv")
Do While strFile <> ""
wb = wb.Open(Filename:=strPath & strFile)
'Loop through the sheets.
For iIndex = 1 To Application.Worksheets.Count
ws = Application.Worksheets(iIndex)
'Loop through the columns.
For iCol = 1 To ws.UsedRange.Columns.Count
'Check row 1 of this column for the char of *
If InStr(ws.Cells(10, iCol).Value, "*") > 0 Then
'We have found a column with the char of *
ws.Columns(iCol).EntireColumn.Delete
ws.Columns(iCol + 1).EntireColumn.Delete
ws.Columns(iCol + 2).EntireColumn.Delete
End If
Next iCol
Next iIndex
wb.SaveAs(Filename:="C:\test\new\" & wb.Name, FileFormat:=xlOpenXMLWorkbook)
wb.Close(SaveChanges:=False)
strFile = Dir()
Loop
MessageBox.Show("The csv files have now been cleaned. Congrats.")
Else inputRadioButton.IsChecked = True
MessageBox.Show("The data has now been split into Trajectory and ForcePlate input files. High 5.")
End If
End Sub
End Class
I get 3 errors but can't work out how to solve them.
a) Worksheets is not a member of Application [line 19]
b) Worksheets is not a member of Application [line 20]
c) 'xlOpenXMLWorkbook' is not declared. It may be inaccessible due to its protection level.
For a) and b), the pattern is :
Application.Workbooks.Worksheets
For c), easiest way out :
Go into VBE from Excel (Alt + F11)
Press F2 to display the Object Browser
Look for xlOpenXMLWorkbook
Result : Const xlOpenXMLWorkbook = 51 (&H33)
So, just replace it by the value 51!
Here is your amended code :
Class MainWindow
Dim wb As Microsoft.Office.Interop.Excel._Workbook
Dim ws As Microsoft.Office.Interop.Excel._Worksheet
Dim iCol As Integer
Dim strName As String
Dim iIndex As Integer
Dim wbIndex As Integer
Dim strPath As String
Dim strFile As String
Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
If cleanRadioButton.IsChecked = True Then
strPath = "c:\test\old\"
strFile = Dir(strPath & "*.csv")
Do While strFile <> ""
wb = wb.Open(Filename:=strPath & strFile)
'Loop through the sheets.
For wbIndex = 1 To Application.Workbooks.Count
For iIndex = 1 To Application.Workbooks(wbIndex).Worksheets.Count
Ws = Application.Workbooks(wbIndex).Worksheets(iIndex)
'Loop through the columns.
For iCol = 1 To Ws.UsedRange.Columns.Count
'Check row 1 of this column for the char of *
If InStr(Ws.Cells(10, iCol).Value, "*") > 0 Then
'We have found a column with the char of *
Ws.Columns(iCol).EntireColumn.Delete
Ws.Columns(iCol + 1).EntireColumn.Delete
Ws.Columns(iCol + 2).EntireColumn.Delete
End If
Next iCol
Next iIndex
Next wbIndex
'Const xlOpenXMLWorkbook = 51 (&H33)
wb.SaveAs(Filename:="C:\test\new\" & wb.Name, FileFormat:=51)
wb.Close(SaveChanges:=False)
strFile = Dir()
Loop
MessageBox.Show ("The csv files have now been cleaned. Congrats.")
Else: inputRadioButton.IsChecked = True
MessageBox.Show ("The data has now been split into Trajectory and ForcePlate input files. High 5.")
End If
End Sub
End Class
To reference a worksheet yau can use either ws = wb.Worksheets(1) or ws = wb.Worksheets("Sheet1") or ws = excelApp.ActiveWorkbook.Worksheets(1) and to use xlOpenXMLWorkbook use the name of the corresponding Enum XlFileFormatas well: XlFileFormat.xlOpenXMLWorkbook.
This simplified example opens the workbook Test.xlsx, writes text in cell A1 and saves it to new folder.
Imports System.IO
Imports Microsoft.Office.Interop.Excel
Public Class MainWindow
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim excelApp As Application
Dim wb As _Workbook
Dim ws As _Worksheet
Dim rng As Range
Dim strPathOld = "c:\temp\old"
Dim strPathNew = "c:\temp\new"
' get excel application reference
excelApp = New Application
excelApp.Visible = True
excelApp.ScreenUpdating = True
' open the workbook
wb = excelApp.Workbooks.Open(Path.Combine(strPathOld, "Test.xlsx"))
' set reference to the sheet with index 1
ws = wb.Worksheets(1)
' or use sheet name
' ws = wb.Worksheets("Sheet1")
' or use ActiveWorkbook if it exists
' ws = excelApp.ActiveWorkbook.Worksheets(1)
' write text in cell A1
rng = ws.Range("A1")
rng.Formula = "Test123"
' save the workbook in new location
wb.SaveAs(Filename:=Path.Combine(strPathNew, wb.Name), _
FileFormat:=XlFileFormat.xlOpenXMLWorkbook)
excelApp.Quit()
End Sub
End Class
Note: add reference to MS Office Interop for your version of Excel(here example for Excel 2007).
My script is pulling some information (filename, date, &c) from a server that contains only (nearly) identical excel files generated by a separate application whenever it is used. The goal is to find out who is using the tool and how often.
I need help with two things: extracting info from within the excel file, and appending the results to the SAME excel file each time it's run instead of creating a new file each time.
Here is what I have...
Imports Excel = Microsoft.Office.Interop.Excel Imports System Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'declare excel objects
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
Dim i As Integer = 2
'I know this is the problem area...
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
xlWorkSheet.Cells(1, 1) = " File Name "
xlWorkSheet.Cells(1, 2) = " Date Created "
'this should be cell B1
xlWorkSheet.Cells(1, 3) = " Requestor "
'this should be cell B21
xlWorkSheet.Cells(1, 4) = " Lead Type"
'get to directory
For Each strFolder As String In _
My.Computer.FileSystem.GetDirectories("Z:\\...")
'get file names
Dim infoReader As System.IO.FileInfo
infoReader = My.Computer.FileSystem.GetFileInfo(strFolder)
'write to excel worksheet
xlWorkSheet.Cells(i, 1) = strFolder
xlWorkSheet.Cells(i, 2) = infoReader.CreationTime
i += 1
Next
xlWorkSheet.SaveAs("C:\...")
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
MsgBox("Excel file created , see file in c:\Documents")
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
Instead of creating a new application and workbook, just use activeworkbook, e.g.
replace
'I know this is the problem area...
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
with
xlWorkBook = xlApp.ActiveWorkbook
xlWorkSheet = xlWorkBook.Sheets("sheetname")
where you replace sheetname with whatever the desired sheet name is.
Alternatively, you could just use ActiveSheet.