EPPLUS Worksheet objects are null if named range is empty - epplus

I'm using EPPlus 6.0.8.
My Excel worksheet has a named range with conditional formatting. If that named range is empty, I get a "object reference not set to an instance of an object" when trying to access just the Workbook or Worksheets.
using (var package = new ExcelPackage(bulkReport.ImportFile))
{
// cannot access any "package.Workbook" members
}
When I debug and set a break point just before package.Workbook null reference, it is null at first. When I refresh the watched workbook, it is no longer null and the code runs.
Stack Trace
at OfficeOpenXml.ExcelRangeBase..ctor(ExcelWorksheet xlWorksheet, String address)
at OfficeOpenXml.ExcelNamedRange..ctor(String name, ExcelWorksheet nameSheet, ExcelWorksheet sheet, String address, Int32 index, Boolean allowRelativeAddress)
at OfficeOpenXml.ExcelNamedRangeCollection.AddName(String Name, ExcelRangeBase Range, Boolean allowRelativeAddress)
at OfficeOpenXml.ExcelWorkbook.GetDefinedNames()
at OfficeOpenXml.ExcelPackage.get_Workbook()
at EPPlus_Test.Program.Main(String[] args) in C:\\Source\\EPPlus Test\\EPPlus Test\\Program.cs:line 22
EDIT 11/3/2022:
I found that one of the Worksheet names contained invalid characters (Tabs in this case). This caused EPPlus to fail. Any way to check the worksheet names through EPPlus?

Related

Find a text in a range using EPPlus

I'm trying to find a text in an excel sheet (ws), but I cannot be sure where exactly will be that text, I only know it will be in a given range (A1:B64).
When I use this code (for test purpouse), it works fine and I can find the value:
var Row as object = From cell In ws.SelectedRange(2,2)
Where cell.Value.ToString().Equals("any text")
Select cell.Start.Row
But when I changed the code to this:
var Row as object = From cell In ws.SelectedRange("A1:B64")
Where cell.Value.ToString().Equals("any text")
Select cell.Start.Row
I get an error that said:
System.NullReferenceException: 'Object reference not set to an instance of
an object.'
OfficeOpenXml.ExcelRangeBase.Value.get returned Nothing.
I also tried change the values for the selected ranges to:
ws.SelectedRange(ws.Dimension.Address)
ws.SelectedRange(ws.Dimension.Start.Row, ws.Dimension.End.Column)
ws.SelectedRange(1,1,64, 2)
ws.Cells("A1:B64")
All of them throw an error.
Any help?
Thanks in advance.
Couldn't it be that you have cells within the range that has no value set? In that case EPPlus will return null and your ToString() call will throw an exception.
Haven't tried this code myself, but maybe you can use the "Safe Navigation Operator" in C#? Like this:
var Row as object = From cell In ws.SelectedRange("A1:B64")
Where cell.Value?.ToString().Equals("any text")
Select cell.Start.Row
I fixed my problem doing this:
Dim Row as object = From cell In ws.SelectedRange("A1:B64")
Where cell.Value <> Nothing AndAlso cell.Value.ToString().Equals("any text")
Select cell.Start.Row

Word VSTO: Save a string as an AutoText value

I am porting a Word vba project that has some older WordBasic elements into a VSTO project using vb.net. One of the tasks I need to do is programmatically save a string, or the contents of a text box on a form, to an AutoText value in the Word template.
In the old project, this was easy. The command looked something like this:
WordBasic.SetAutoText "AT Name", strSomeValue, 0
Attempting this in vb.net:
'declarations
Public appWord As Word.Application
Public tplMyTpl As Word.Template
Public doc As Word.Document
'Get the template
appWord = Me.Application
doc = appWord.ActiveDocument
tplMyTpl = doc.AttachedTemplate
'try saving autotext
tplMyTpl.AutoTextEntries.Add("AT Name", strSomeValue)
does not work because the AutoTextEntries.Add method only accepts the value as a Word.Range. A type cast error is thrown at runtime with the code above. It would have to look something like:
dim sel as Word.Selection = appWord.Selection
tplMyTpl.AutoTextEntries.Add("AT Name", sel.Range)
Problem is I do not want to insert the string into my document, select it as a Range, save the AutoText entry then delete the text. That seems like extremely sloppy coding.
You can still use WordBasic in VSTO. Just call it through your Word.Application object reference, e.g.:
appWord.WordBasic.SetAutoText("AT Name", strSomeValue, 0)
Tested and working in Word 2013.

Single line thread/sequenced execution of formulas in Excel

I wrote a simple macro function in VBA for Excel to extract text appearing in a particular location in an HTML document, first retrieving the HTML document from a URL value in another cell. The macro function itself is not important, except for the fact that it sends an HTTP request and creates an HTML file object, which I fear will cause Excel to crash if I paste, say, a column of 100 or more URLs and it starts trying to calculate all the values at once. I can see that it stops and churns for a moment if I drag the formula down 10 cells where there is already a column of URLs. Is there a setting to force Excel to calculate one formula at a time, so that it may take longer but is less likely to freeze up or crash?
Update: I incorporated a static collection variable into the function to at least avoid repeated slowdowns retrieving the same HTML in the same worksheet:
Function GetUSPatentAbstract(ByVal url As String) As String
Static colAbstract As New Collection
Dim abstract As String
On Error Resume Next
abstract = colAbstract(url)
`If there is no abstract for the URL in the collection yet, then it is retrieved:
If Err.Number <> 0 Then
Dim description As String
Dim abstractStart As Long
Dim abstractEnd As Long
Dim abstractLength As Long
Set html_doc = CreateObject("htmlfile")
Set xml_obj = CreateObject("MSXML2.XMLHTTP")
xml_obj.Open "GET", url, False
xml_obj.send
html_doc.body.innerhtml = xml_obj.responseText
Set xml_obj = Nothing
description = html_doc.body.innertext
abstractStart = InStr(description, "Abstract") + 8
abstractEnd = InStr(description, "Inventors:")
abstractLength = abstractEnd - abstractStart
abstract = Mid(description, abstractStart, abstractLength)
colAbstract.Add Item:=abstract, Key:=url
End If
On Error GoTo 0
GetUSPatentAbstract = abstract
End Function

vb.net "PasteSpecial method of Range class failed"

I'm trying to write an application in VB.net that assembles an Excel Workbook by wisely coping cells from another opened Workbook. [Note: as for now, the two workbooks are opened within the same Excel application - Originally I was using two different Excel instances, but only later I realized that the PasteSpecial between two Instances behaves differently]
I'm using Visual Studio 2012, Excel 2007 and I'm including Microsoft Excel 12.0 Object Library in the project references
The code is something like that:
Dim appXL As Excel.Application
Dim wbXLsource As Excel.Workbook
Dim wbXLtarget As Excel.Workbook
''with two different buttonclick event handlers
''I assign wbXLsource and wbXLtarget
''the full code is omitted
...
wbXLsource = appXL.Workbooks.Open(strFileNameAndPath)
...
...
wbXLtarget = appXL.Workbooks.Add
...
''I use a third button handler for the
''Copy and PasteSpecial Operations
Private Sub btnAppendWorksheet_Click(sender As Object, e As EventArgs) _
Handles btnAppendWorksheet.Click
Dim shXLtar As Excel.Worksheet
Dim shXLsou As Excel.Worksheet
shXLtar = wbXLtarget.ActiveSheet
shXLtar.Cells.Clear()
shXLsou = wbXLsource.ActiveSheet
shXLsou.Range("A1:H433").Copy()
Try
shXLtar.Range("A1:H433").PasteSpecial(Excel.XlPasteType.xlPasteAll, False, False) ''Paste special Format:=
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
The PasteSpecial method throws the exception "PasteSpecial method of Range class failed".
What is strange is that the same code originally worked within two workbooks that run in different Excel instances [At that time I had appXLtarget and appXLsource].
Needless to say that I tried all the possible combinations of "Selection", "Activate" in any part of the code: eg between Copy and PasteSpecial etc etc.
Probably there is something really coarse that I'm missing <- I'm new of VB.net
Thanks for any help and Best Regards!
If you are new in VB.Net, you should first do research about OptionStrict. With optionStrict set to ON, VS won't compile your code...
Replace
shXLtar.Range("A1:H433").PasteSpecial(Excel.XlPasteType.xlPasteAll, False, False)
With
shXLtar.Range("A1:H433").PasteSpecial(Excel.XlPasteType.xlPasteAll,Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone,False, False)
or
shXLtar.Range("A1:H433").PasteSpecial(Excel.XlPasteType.xlPasteAll)
Hope this helps.

How do I assign a value to a property where the property name is supplied at runtime in VBA?

I'm trying to create a worksheet that creates a list of values that will be used to initialize the values of an instantiated class.
For example, I might have the following in my initialization worksheet:
Property Name Value
StartingCol A
StartingRow 11
I'd then create a class that would parse this worksheet and provide me with an enumberable that I could use to initialize the properties of an instantiated object. However, I'm not sure how I might be able to specify the property value at runtime using a string rather than specifying it explicitly in code. You can get an idea of what I'm trying to accomplish in the code below:
Sub test_PropertyAssignment()
Dim sp As SheetParser
Dim strFieldName As String
Dim strFieldNameValue As String
Set sp = New SheetParser
'The property name is supplied explicitly'
sp.StartingCol = "B"
strFieldName = "StartingCol"
strFieldNameValue = "B"
sp.[how can I supply strFieldName to specify the property?] = strFieldNameValue 'Will not Work'
End Sub
Is there a way to use a string at runtime to specify the property name rather than specifying explicitly in code?
Look up the CallByName function in the VBA help.
You should be able to do something like:
Call CallByName(sp,strFieldName,vbLet,strFieldNameValue)