You are on page 1of 12

Chapter xx: Communicating with Excel

■ Introduction
There are many situations where it is useful to exchange information (in either direction) between NX and Excel.
For example, you might want to export an NX bill-of-material or other report to Excel. Alternatively, you might want
to import data from an Excel spreadsheet and use this to assign values to attributes in NX. There are two somewhat
separate steps in the data exchange process: getting data into and out of NX, and getting data into and out of Excel.
These two steps are both discussed in this chapter, even though the second one is not really related to NX.
There are (at least) three different ways to programmatically “push” data to Excel:
 The Automation Approach: use the Excel API to write data into an Excel document.
 The CSV Approach: write a csv file that can then be imported into Excel.
 The XML Approach: write an XML file that can then be imported into Excel
These are discussed in the sections below. However, note that the first and second of these are somewhat related,
so you should read about automation even if you’re primarily interested in csv files.
The final section in this chapter discusses importing data from Excel.
Many of the code examples given below are just fragments, as usual. The complete code is provided in four folders
in C:\Program Files\Siemens\NX 8.5\UGOPEN\SNAP\Examples\More Examples. The four folders are called
Excel Automation, Excel Write CSV, Excel Write XML, and Excel Read.

■ Some Sample Data


In the discussion below, we’re going to be using a simple fictitious dataset that just consists of three spheres. These
spheres will have attribute data, as shown in the following table, that we’re going to export to Excel in several
different ways. This is just “fake” data for illustration purposes, of course. Unless you’re in the billiard equipment
business, your parts will probably be a lot more complicated than spheres . In a realistic scenario, the bodies and
parts would probably have been created interactively by NX users.

Part Number Weight Cost Purchase Date


123456123456123456 14.75 $1,995 03-Feb-2012

234567234567234567 2.75 $675 11-Jun-2012

345678345678345678 0.25 $69 17-Dec-2011

Here is some code that creates the three spheres and assigns the attributes:

Private Shared Sub CreateParts()


Dim s1 As Snap.NX.Body = Snap.Create.Sphere( {0, 0, 0}, 1 ).Body
Dim s2 As Snap.NX.Body = Snap.Create.Sphere( {3, 3, 0}, 1 ).Body
Dim s3 As Snap.NX.Body = Snap.Create.Sphere( {6, 6, 0}, 1 ).Body
s1.SetStringAttribute("Part Number", "123456123456123456")
s2.SetStringAttribute("Part Number", "234567234567234567")
s3.SetStringAttribute("Part Number", "345678345678345678")
s1.SetRealAttribute("Weight", 14.75)
s2.SetRealAttribute("Weight", 2.75)
s3.SetRealAttribute("Weight", 0.25)
s1.SetIntegerAttribute("Cost", 1995)
s2.SetIntegerAttribute("Cost", 675)
s3.SetIntegerAttribute("Cost", 69)
s1.SetDateTimeAttribute("Purchased", New System.DateTime(2012, 2, 3))
s2.SetDateTimeAttribute("Purchased", New System.DateTime(2012, 6, 11))
s3.SetDateTimeAttribute("Purchased", New System.DateTime(2011, 12, 17))
End Sub

Getting Started with SNAP Chapter xx: Communicating with Excel Page 1
This CreateParts function will be called in each of the examples below, to provide us with some sample data that we
can then transfer to Excel.

■ The Automation Approach


Since its earliest days, Excel has had an API that you can call to gain access to its functions. Driving Excel from a
user-written program in this way is known as “Excel Automation”, and the API is known as the “Automation API”.
The Excel API was originally built around a technology called COM, which was popular in the 1990’s. Specifically,
the Excel objects that are exposed by this original API are COM objects, and Excel is said to be a “COM server”.
Although Excel has changed dramatically over the last 20 years, its API is still fundamentally based on COM.
Today, many people want to use .NET languages like Visual Basic and C# to automate Excel, so there needs to be
some way to access the COM API from these languages. The solution is an interoperability layer — a collection of
functions that “wrap” the COM API and make it easier to call from .NET code. The wrapper functions are contained
in DLLs called “interoperability assemblies”, which you must reference in order to access the Excel functions. Of
course, if you want to call Excel functions, you still need a copy of Excel itself; the interoperability assemblies are
just the glue layer, so they are not sufficient by themselves.

Excel Macros
The functions in the Excel API (whether wrapped or not) correspond very closely with the functions of interactive
Excel. As with NX, you can understand this correspondence by recording macros in Excel and examining their
contents. For example, if you record the actions of typing “xyz” into cell C3, and making it bold, your macro will
contain the following code:

Range("C3").Select
ActiveCell.FormulaR1C1 = "xyz"
Selection.Font.Bold = True

This code uses the VBA language (Visual Basic for Applications), but translating it into VB.NET or other languages
is typically straightforward. NX has a nice advantage in this area, of course —it can record and play back macro
code in several languages, not just one.

Required References
The approach here is to call Excel API functions to write the attribute data into the cells of a newly-created
worksheet. To gain access to these functions, our code will need a reference to Microsoft.Office.Interop.Excel. As its
name suggests, this is the interoperability assembly for Excel, and you can find it on the .NET tab of the Add
Reference dialog in Visual Studio, as shown below:

On the COM tab, you can find another Excel library, called Microsoft Excel 14.0 Object Library. This will work, too,
but the one on the .NET tab is preferable.

Getting Started with SNAP Chapter xx: Communicating with Excel Page 2
Example Code
The code to write the data is as follows:

Imports Excel = Microsoft.Office.Interop.Excel


Public Class AutomateExcel
Public Shared Sub Main()
' Create some fake data
CreateParts()
Dim app As Excel.Application = New Excel.Application()
app.Visible = True
Dim workBook As Excel.Workbook = app.Workbooks.Add()
Dim sheet As Excel.Worksheet = workBook.ActiveSheet
Dim cells As Excel.Range
' Change the formatting of the columns
cells = sheet.Columns(1)
cells.NumberFormat = "@" ' Format column #1 as text
cells.ColumnWidth = 22 ' Adjust the column width
cells = sheet.Columns(2)
cells.NumberFormat = "0.00" ' Format column #2 with 2 decimal places
cells = sheet.Columns(3)
cells.NumberFormat = "$#,##0" ' Format column #3 as currency
cells = sheet.Columns(4)
cells.NumberFormat = "dd-mmm-yyy" ' Format column #4 as dates
' Write the attribute data into cells
For i As Integer = 1 To Snap.Globals.WorkPart.Bodies.Length
Dim part As Snap.NX.Body = Snap.Globals.WorkPart.Bodies(i-1)
cells = sheet.Cells(i, 1) : cells.Value = part.GetStringAttribute("Part Number")
cells = sheet.Cells(i, 2) : cells.Value = part.GetRealAttribute("Weight")
cells = sheet.Cells(i, 3) : cells.Value = part.GetIntegerAttribute("Cost")
cells = sheet.Cells(i, 4) : cells.Value = part.GetDateTimeAttribute("Purchased")
Next
' Save, close, and quit
workBook.SaveAs("C:\public\parts.xlsx")
workBook.Close()
app.Quit()
' Clean up COM objects (details later)
Cleanup(cells, sheet, workBook, app)
End Sub
End Class

Most of the code is straightforward, and should be easy to understand. One thing to note is that cell numbering in
Excel starts at 1, not at 0. So, cell “C2” is Cells(2,3), for example.
As you can see, the code saves the Excel file into a folder called C:\public. You can use a different folder, instead, of
course, as long as it’s one for which you have write access.
The only real mystery in the code is the last step, where we “clean up COM objects”. This step is necessary because
the Excel API we’re using is, at its core, a COM API. When our VB code defines objects like the Excel application, the
workbook, and the worksheet, hidden COM objects are created, and the normal .NET garbage collection is unable to
handle these. So, when we are finished with these objects, we have to take care of destroying them and free-ing
their memory.
Note that cleaning up the COM objects always has to be done in the reverse order from their creation. So, in this
case, the order had to be cells, sheet, workBook, app.

Getting Started with SNAP Chapter xx: Communicating with Excel Page 3
Some code to do this cleanup is shown below. Don’t worry if you don’t understand it — many experienced
programmers don’t understand it very well, either. Just place this code inside your AutomateExcel class, accept that
it’s necessary, and try not to worry about it too much.

Private Shared Sub Cleanup(ParamArray objs As Object())


GC.Collect()
GC.WaitForPendingFinalizers()
For Each obj As Object In objs
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Next
End Sub

If you really want to know more about COM object cleanup, you can start by reading this discussion. But note that
that most of the suggestions essentially say “I tried this, and it seems like it worked, maybe, but I don’t know why”.
Running the code should produce an Excel spreadsheet that looks something like this:

Text Versus Numbers


You may have noticed that our code formatted the first column as text, even though our part numbers are
numerical. Excel thinks this might be a mistake, and displays the little green triangles in the “A” column to get our
attention. But, in fact, there is no mistake — text formatting is the right choice in this situation. To understand why,
try removing the two lines of code that say:

cells = sheet.Columns(1)
cells.NumberFormat = "@" ' Format column #1 as text

If you rebuild and run the modified code, the result will be this spreadsheet:

Since we are no longer providing any help, Excel tries to make a guess about the items in column #1, and it guesses
that they should be numbers, and stores them internally as numbers. But, Excel numbers only have around 15
digits of precision, so, as the display in the formula bar shows, the last 3 digits of each part number have been lost.
Clearly, text formatting (and text storage) is the right choice, here.

■ The CSV Approach


A “CSV” file is a simple text file consisting of “comma separated values”. Each line of text represents a data record
that will become a row of the eventual spreadsheet. Within each line, the data “fields” are separated by commas or
other delimiters. These files can be imported into Excel either manually, by a user running Excel, or
programmatically using functions in the Excel automation API. The main benefit of CSV files is their simplicity. This
means that they are easy to write, and can be imported into a wide range of spreadsheet and database applications.

Getting Started with SNAP Chapter xx: Communicating with Excel Page 4
Writing a CSV File
Using the same fabricated data as before, the code to write a csv file is as follows:

Imports Excel = Microsoft.Office.Interop.Excel

Class WriteCsv

Public Shared Sub Main()

' Create the usual fake data


CreateParts()

' Use a semi-colon as the delimiter


Dim delim As String = ";"
Dim lineList = New List(Of String)

' Gather up the attribute data


For Each part in Snap.Globals.WorkPart.Bodies
Dim line, partNumber, weight, cost, purchaseDate As String
partNumber = part.GetStringAttribute("Part Number")
weight = part.GetRealAttribute("Weight").ToString("0.00")
cost = part.GetIntegerAttribute("Cost")
purchaseDate = part.GetDateTimeAttribute("Purchased").ToString("MM/dd/yyyy")
line = partNumber & delim & weight & delim & cost & delim & purchaseDate & vbCr
lineList.Add(line.ToString())
Next

' Write the data out to a text file


System.IO.File.WriteAllLines("C:\public\data.txt", lineList)

End Sub

End Class

As you can see, the file we created is arguably not a “csv” file. It actually uses semicolons as delimiters, not commas,
and it has the file extension “txt”, rather than “csv”. But, anyway, it’s a text file with fields separated by delimiters,
which is all that really matters. Note how we have used the ToString function to format the weight and purchase
date attributes appropriately.
The user could just manually import this file into Excel, of course, so we could stop at this point. But importing text
files into Excel requires a bit of expertise, so, to avoid inconsistencies and mistakes, it’s better if we can automate it.

The OpenText Function


To import a text file (or a “csv” file) into Excel, we use the OpenText function, which has the following arguments:

Argument Name Data Type Description


Path String The path name (including extension) of the text file to be imported.
Origin Object The platform or geographic origin of the text file. See below for details.
StartRow Object The line number at which to start parsing lines of text in the input file.
(Integer) The numbering starts at “1”, which is the default value.
DataType Object Specifies the column format of the data in the file. Can be one of the
(XlTextParsingType) following XlTextParsingType constants: xlDelimited or
xlFixedWidth. If this argument is not specified, Microsoft Excel
attempts to guess the column format when it opens the file.
TextQualifier XlTextQualifier The text qualifier. This is explained below.
ConsecutiveDelimiter Object True to have consecutive delimiters considered as one single delimiter.
(Boolean) The default is False.
Tab Object True to have the tab character be a field delimiter.
(Boolean) The default value is False.
Semicolon Object True to have the semicolon character be a field delimiter.
(Boolean) The default value is False.
Comma Object True to have the comma character be a field delimiter.
(Boolean) The default value is False.

Getting Started with SNAP Chapter xx: Communicating with Excel Page 5
Space Object True to have the space character be a field delimiter.
(Boolean) The default value is False.
Other Object True to have the character specified by the OtherChar argument be a
(Boolean) field delimiter. The default value is False.
OtherChar Object (required if Other is True). Specifies the delimiter character when
(String) Other is True. If more than one character is specified, only the first
character of the string is used.
FieldInfo Object(2, n) A two-dimensional array containing parse information for individual
columns of data. See below for further details.
TextVisualLayout XlTextVisualLayoutType The visual layout (direction) of the text. The default is the system
setting (I think) which will usually be xlTextVisualLTR (left-to-right),
unless you are using a language like Hebrew.
DecimalSeparator Object The decimal separator that Microsoft Excel uses when recognizing
(String) numbers. The default setting is the system setting.
ThousandsSeparator Object The thousands separator that Excel uses when recognizing numbers.
(String) The default setting is the system setting.
TrailingMinusNumbers Object Specify True if numbers with a minus character at the end should be
(Boolean) treated as negative numbers. If False or omitted, numbers with a
minus character at the end are treated as text.
Local Object Specify True if regional settings of the machine should be used for
(Boolean) separators, numbers and data formatting.

The arguments correspond closely to those available in the Excel “Text Import Wizard” that is invoked when you
open a text file interactively from within Excel:

So, you can get a better understanding of the arguments by recording a macro while you import a text file. Some of
the more puzzling ones are described in detail in the paragraphs below.
Origin: This can be one of the following XlPlatform constants: xlMacintosh, xlWindows, or xlMSDOS.
Alternatively, it can be an integer indicating the number of the desired code page. The allowable integer values are
shown in the “File origin” menu in the Text Import Wizard:

One of the most useful values is 65001, which corresponds to Unicode text in UTF-8 encoding. If this argument is
omitted, the method uses the current setting from the Text Import Wizard.
TextQualifier: This is a character that can be used to enclose a sequence of characters, thereby forcing them to
become one cell, even if they include a delimiter character. For example, suppose that commas are being used as
delimiters. Then the string 1,260 would be split into two cells, even though the intention is probably to create a
single cell containing the number 1260. Similarly, we would probably want to force the string “Monday, July 4th” to
be a single cell. Of course, if you choose delimiter characters that don’t appear within the data itself, then there is
no need for a TextQualifier. That’s why our examples use a semi-colon as the delimiter.

Getting Started with SNAP Chapter xx: Communicating with Excel Page 6
There is widespread confusion about the TextQualifier argument, possibly as a result of its poorly chosen name.
Many people think that using this argument will force Excel to format the enclosed strings as text (rather than as
numbers). This is not correct. To force Excel to format data as text, you must use the “FieldInfo” parameter.
FieldInfo: This is a two-dimensional array indicating how various columns of data should be parsed and formatted
during import. It is easiest to think of it as a list of pairs of the form (columnNumber, dataType), where
columnNumber indicates which column is under consideration, and dataType is one of the enumerated values from
Excel.XlColumnDataType. The most interesting values of this enum are:

Argument Value How Data is Parsed and Formatted


Excel.XlColumnDataType.xlTextFormat As text
Excel.XlColumnDataType.xlGeneralFormat Using Excel’s built-in general rules
Excel.XlColumnDataType.xlMDYFormat As a M/D/Y date (other date formats are available)
Excel.XlColumnDataType.xlSkipColumn Skipped (not parsed and not imported)

As an example, consider the following code:

Dim text As Excel.XlColumnDataType = Excel.XlColumnDataType.xlTextFormat


Dim date As Excel.XlColumnDataType = Excel.XlColumnDataType.xlMDYFormat
Dim format As Object(,) = { {1, text}, {3, date}, {4, text} }

The first two lines just define variables with short names, for convenience. Then the third line says that
 Columns #1 and #4 (the “A” column and the “D” column) should be formatted as text,
 Column #3 (the “C” column) should be formatted as dates
 All other columns should be parsed and formatted as “general”.
The order of the pairs doesn’t matter. The code

Dim format As Object(,) = { {4, text}, {1, text}, {3, date} }

gives the same result as the code above. If there's no column specifier for a particular column of input data, the
column is parsed with the General setting, which means that Excel will try to guess the correct format. If the
column contains strings that Excel can recognizes as dates, for example, then this column will be formatted as dates
even though you specified a “general” format or no format at all.
If you specify that a column is to be skipped, you must explicitly state the type for all the other columns, or the data
will not parse correctly.
The xlDMYFormat date format seems to have some bugs, but the xlMDYFormat one works fine. Having spaces at the
beginning of a date field will confuse the parsing, just as it does when typing into Excel.

Simplified Calls to the OpenText Function


Since the OpenText function has 18 arguments, calling it can be a bit complicated. However, note that only the first
argument (the file pathname) is required, so we can omit many of the others, if we want to.
In its full form, a call would look something like this:

workbooks.OpenText(
pathName, origin, startRow,
dataType, textQualifier, consecutiveDelimiter,
useTab, useSemicolon, useComma, useSpace, useOther, otherChar,
myFormat,
textVisualLayout,
decimalSeparator, thousandsSeparator, trailingMinusNumbers, local)

Getting Started with SNAP Chapter xx: Communicating with Excel Page 7
But we can take advantage of Visual Basic’s ability to omit optional arguments, and write this, instead:

workbooks.OpenText(
pathName,
Semicolon := True,
DataType := Excel.XlTextParsingType.xlDelimited,
FieldInfo := myFormat)

The “:=” syntax is used to give values to optional named arguments. Some people use sequences of commas when
omitting arguments, or they use System.Type.Missing as a placeholder, but the approach shown above seems
easier to read and less error-prone.

A Simple Example
The code given earlier creates a simple text file called data.txt, with the following contents:
123456123456123456;14.75;1995;02/03/2012
234567234567234567;2.75;675;06/11/2012
345678345678345678;0.25;69;12/17/2011
The code to import this file would be as follows. Again, note that you’ll need a a reference to the
Microsoft.Office.Interop.Excel assembly to use this code

Imports Excel = Microsoft.Office.Interop.Excel

Class OpenTextExample

Public Shared Sub Main()

Dim app As Excel.Application = New Excel.Application()


app.Visible = True

Dim path As String = "C:\public\data.txt"


Dim myType As Excel.XlTextParsingType = Excel.XlTextParsingType.xlDelimited

' Define some abbreviations for column formats, for convenience


Dim t As Excel.XlColumnDataType = Excel.XlColumnDataType.xlTextFormat
Dim g As Excel.XlColumnDataType = Excel.XlColumnDataType.xlGeneralFormat
Dim d As Excel.XlColumnDataType = Excel.XlColumnDataType.xlMDYFormat

' Format column #1 as text, #2 as general, and #4 as date


Dim myFormat As Object(,) = { {1, t}, {2, g}, {4, d} }

' Import the data file, which will add a new item to the Workbooks collection
Dim workBooks As Excel.Workbooks = app.Workbooks
workBooks.OpenText(path, DataType:=myType, Semicolon:=True, FieldInfo:= myFormat)

' Save, close, and quit


Dim workBook As Excel.Workbook = app.ActiveWorkbook
Dim fileFormat As Excel.XlFileFormat = Excel.XlFileFormat.xlOpenXMLWorkbook
workBook.SaveAs("C:\public\parts.xlsx", fileFormat)
workBook.Close()
app.Quit()

' Clean up COM objects


Cleanup(workBook, workBooks, app)

End Sub

End Class

This produces the following result:

Getting Started with SNAP Chapter xx: Communicating with Excel Page 8
Specifying the DataType as XlDelimited is necessary, or else Excel will interpret the file as having fixed-width
fields. As you can see, we have asked for the first column to be parsed and formatted as text. Without this request,
the part numbers would be interpreted and stored as numbers, which would cause problems, as we saw earlier.
Also, we need to specify the “general” format for the second column, or else Excel will mysteriously interpret the
2.75 in cell B2 as a date (February 1st 1975). Since we’re calling Excel API functions, some COM object cleanup is
needed, again.

Further Formatting
With the approach outlined above, the only formatting controls available to us are the rudimentary ones provided
by the OpenText function. But, once we have imported the data, we can use other Excel API functions to format it
further, as we saw earlier in this chapter. The code to do this is as follows:

Dim workSheet As Excel.Worksheet = workBook.ActiveSheet


Dim cells As Excel.Range

cells = workSheet.Columns(1)
cells.Font.Bold = True ' Make column #1 bold
cells.ColumnWidth = 22 ' Adjust its width
cells = workSheet.Columns(2)
cells.NumberFormat = "0.00" ' Format column #2 with 2 decimal places
cells = workSheet.Columns(3)
cells.NumberFormat = "$#,##0" ' Format column #3 as currency
cells = workSheet.Columns(4)
cells.NumberFormat = "dd-mmm-yyy" ' Change the date format in column #4

You can insert this code after the call to OpenText and before the save/close/quit steps. Note that this code
introduces two new COM objects (workSheet and cells), which we will need to clean up. So, our call to the
Cleanup function must be modified to read as follows:

' Clean up COM objects


Cleanup(cells, workSheet, workBook, workBooks, app)

Running the code produces the following results in Excel:

Note the little green triangles in the “A” column. Excel is telling us that the items in this column look like numbers,
but we have formatted them as text, which might be a mistake. As we know, it’s not a mistake, in this case, but Excel
gives us the helpful hint, anyway.

Import First and Format Later?


Since the FieldInfo argument of the OpenText function is a bit complicated, it’s tempting to just import data in the
simplest way possible, and then reformat it later. Unfortunately, this doesn’t always work. In the example above,
suppose we did not specify any formatting information at all when calling the OpenText function. Our code would
be quite a bit simpler. We wouldn’t need the FieldInfo argument, and our code to do the import would just be:

workBooks.OpenText(path, DataType:= myType, Semicolon:=True)

But the result in Excel would be this:

Getting Started with SNAP Chapter xx: Communicating with Excel Page 9
This is the same problem we saw earlier — Excel has stored the part numbers as numbers, rather than text, so we
have lost the last three digits, and no subsequent reformatting operation will be able to recover them.

■ The XML Approach


Beginning with Office 2007, the file formats of Word, Excel and PowerPoint were changed completely. The new
format is conceptually very simple — a document is just a collection of XML files that are bundled together in a zip
container. The overall scheme is called OpenOffice XML, and the constituent pieces use formats called
SpreadsheetML, DrawingML, and so on. Microsoft provides a software library called the Open XML SDK containing
functions that make it easier to work with the XML data. For many scenarios, this is now the recommended way of
reading and writing MS Office documents.
One advantage of the XML-based approach is that it allows a spreadsheet document to be created and formatted
without using the Excel API functions, which means that it will work on a machine that has no access to Excel itself.
Another advantage is that the functions in the Open XML SDK use strong typing. In the Excel Automation API, many
functions arguments are of type Object, so you get very little help from Intellisense or from type checking during
program editing and compilation. Strong typing makes it easier to write error-free code. So, to proceed, please
download the Open XML SDK from this web site, and install it.
However, the Open XML SDK is very complex, and using it by itself is quite laborious. Much of the effort can be
reduced by using various third-party add-on packages. The code shown below uses an open source package called
ClosedXML, which is freely available from this web site, but there are many others. The required ClosedXML DLL is
included in the sample application in […NX]\UGOPEN\SNAP\Examples\More Examples\Excel Write XML.
Once you have the Open XML SDK and ClosedXML set up correctly, the code to write the data looks like this:

Imports Excel = ClosedXML.Excel


Public Class WriteOpenXML
Public Shared Sub Main()
' Create the usual fake data
CreateParts()
Dim workBook As Excel.XLWorkbook = New Excel.XLWorkbook()
Dim sheet As Excel.IXLWorksheet = workBook.Worksheets.Add("Parts Sheet")
sheet.Column(1).Width = 22 ' Adjust width of column #1
sheet.Column(1).Style.Font.Bold = True ' Make it bold
sheet.Column(1).Style.NumberFormat.Format = "@" ' Format column #1 as text
sheet.Column(2).Style.NumberFormat.Format = "0.00" ' Format with 2 decimal places
sheet.Column(3).Style.NumberFormat.Format = "$#,##0" ' Format as currency
sheet.Column(4).Style.NumberFormat.Format = "dd-mmm-yyy" ' Format as dates
' Write the attribute data into cells
For i As Integer = 1 To Snap.Globals.WorkPart.Bodies.Length
Dim part As Snap.NX.Body = Snap.Globals.WorkPart.Bodies(i-1)
sheet.Cell(i, 1).Value = part.GetStringAttribute("Part Number")
sheet.Cell(i, 2).Value = part.GetRealAttribute("Weight")
sheet.Cell(i, 3).Value = part.GetIntegerAttribute("Cost")
sheet.Cell(i, 4).Value = part.GetDateTimeAttribute("Purchased")
Next
' Save as an xlsx file
workBook.SaveAs("C:\public\parts.xlsx")
End Sub
End Class

This produces the now familiar results in Excel:

Getting Started with SNAP Chapter xx: Communicating with Excel Page 10
Note that we didn’t need to do any of the usual COM object cleanup. We called ClosedXML functions, not the Excel
COM API, so no COM objects were created, and there’s nothing to clean up.
You can accomplish the same thing using the plain Open XML API, or you can even write the XML yourself, if you
have the patience and expertise. To find out how to do this, you could start with this tutorial. If you really want to
understand the details, you will find the Open XML SDK “Productivity Tool” to be very useful. This is a “document
reflector” that can show the XML structure of any Office document, plus the Open XML code needed to create it:

■ Importing From Excel


In this last section of this chapter, we’ll discuss moving data in the opposite direction — from Excel to NX. Suppose
we have some part properties stored in an Excel spreadsheet, as shown below, and we want to assign these as
attribute values within NX.

The required code is as follows:

Public Shared Sub Main()


' Create some fake data (three spheres)
Dim s1 As Snap.NX.Body = Snap.Create.Sphere( {0, 0, 0}, 1 ).Body
Dim s2 As Snap.NX.Body = Snap.Create.Sphere( {2, 2, 0}, 1 ).Body
Dim s3 As Snap.NX.Body = Snap.Create.Sphere( {4, 4, 0}, 1 ).Body
Dim parts As Snap.NX.Body() = { s1, s2, s3 }
Dim app As Excel.Application = New Excel.Application()
Dim workBooks As Excel.Workbooks = app.Workbooks
Dim workBook As Excel.Workbook = workBooks.Open("C:\public\partinfo.xlsx", ReadOnly:= True)
Dim sheet As Excel.Worksheet = workBook.Worksheets("Part Data")
Dim cells As Excel.Range = sheet.Cells
Dim partNum As String
Dim weight As Double
Dim cost As Integer
Dim purDate As System.DateTime
'Read cell values and write them as attributes
For i As Integer = 3 To 5
partNum = cells(i, 2).Value : parts(i-3).SetStringAttribute("Part Number", partNum)
weight = cells(i, 3).Value : parts(i-3).SetRealAttribute("Weight", weight)
cost = cells(i, 4).Value : parts(i-3).SetIntegerAttribute("Cost", cost)
purDate = cells(i, 5).Value : parts(i-3).SetDateTimeAttribute("Purchase Date", purDate)
Next
'Close, and quit
workBook.Close()
app.Quit()
' Clean up COM objects
Cleanup(cells, sheet, workBook, workBooks, app)
End Sub

Getting Started with SNAP Chapter xx: Communicating with Excel Page 11
Using Edit Properties within NX, you can see that the attributes of the first sphere body have been set like this:

■ Other Office Applications


The techniques outlined in this chapter will work with other MS Office applications, too. For example, you could
read specifications from a document written in Microsoft Word, or automatically generate PowerPoint slides for
presentations. The documentation of the Word and PowerPoint APIs is just as bad as Excel’s (or worse), but you
can usually discover what you need to know by recording macros and examining their contents. Also, the
Open XML SDK “Productivity Tool” mentioned earlier has the remarkable ability to show you what code you would
need to write to create any Office document.

Getting Started with SNAP Chapter xx: Communicating with Excel Page 12

You might also like