Click here to Skip to main content
Click here to Skip to main content

TblProc: OpenOffice Calc and Excel

By , 29 Jan 2009
 
Screenshot - TblProc.jpg

This is an updated version of the article and sources. Changes in v1.1:

  • OpenOffice 3.0 support
  • OpenOffice 2.x is not supported anymore (but minor project changes should make it work)
  • Chart (diagram) support added

Introduction

Using C# with OpenOffice.org Calc sometimes seems to be quite a problem. And creating reports using different table processors (Excel and OOo Calc) separately is a bad habit and will be a source of errors in future.

So I hope this article (and source code, of course) will make "cross-table processor" life for C# programmers a bit easier. You won't find a comprehensive solution for using both table processors here (some functionality is not implemented for OpenOffice and "cross-table-processor" interface is quite small too), but I believe that my library is:

  1. Useful for creating simple reports (I use it myself for small business solutions)
  2. A tool which makes communication with OpenOffice Calc easier (even if you wouldn't use the Excel and abstract parts of the library)
  3. A good source of OpenOffice Calc samples for C#

For historical reasons, I started working with Excel and later I had to convert my projects to use both — OOo and Excel. That's why the abstract table processor's interface is much like the Excel's one. Having experience working with Excel API should help you understand the code better.

Design

The basic design is quite simple:

  • 4 abstract base classes:
    • TableProcessor
    • TableSheet
    • TableRange
    • TableDiagram
  • 4 Excel classes, derived from abstract classes mentioned:
    • ExcelApp
    • ExcelSheet
    • ExcelRange
    • ExcelDiagram
  • and similarly, 4 OpenOffice Calc classes:
    • OOApp
    • OOSheet
    • OORange
    • OODiagram

I hope you've got the naming scheme and I have no need to draw the inheritance diagram.

Also, there is a set of enums for constants, constant converter (my consts to Excel or OOo) and several support classes.

The INull interface and classes which implement it are designed to support the "Null object" pattern.

Abstract Interface

TableProcessor — Used for an "Application Object"

  • ExcelAvailable and OOAvailable

    These props should be used for determining if the desired table processor is installed. Both methods are based on a registry query. For OOo, it looks like this query determines only if the whole OpenOffice is installed, but I can't find any better solution.

  • CreateNextPage

    Maybe, should be named CreateNextSheet. Guess what it does ... The startRow parameter is discussed below.

  • this[int]

    TableSheet accessor. By sheet number, starting from 0.

  • CreateAvailable and overloads

    Static factory methods. Creates ExcelApp if Excel available, else creates OOApp (if OOo is available) or throws NoTableProcessorAvailableException if nothing was found.

  • CreateExcel and CreateOO methods

    Allow you to create the table processor you need directly.

TableSheet — Represents a Single Table Processor Page

  • CurrentRow (_curRow inside the class)

    Can help you create reports row by row. You can use it for your own needs, but the common usage is for the AddArray method (see below). The initial value (default is 1) is specified by the startRow parameter for TableProcessor.CreateNextPage or TableProcessor.CreateAvailable. Row indexes start from 1 (Excel style).

  • AddArray

    Adds an array you give it, starting at cell [CurrentRow, 1] and increases the CurrentRow according to the array's height. Row and cell indexes start from 1.

  • CreateAvailable

    Static method. Uses TableProcessor.CreateAvailable, but you get the TableSheet reference at once. Useful for single-page reports.

  • Cell, Range

    Gives you a TableRange object for the cell range you requested. Again, cell indexes start from 1.

  • AddDiagram(TableRange dataRange, RowsCols rowsCols, 
    			DiagramType type, DrawRect rect)

    Adds a chart. New method in v1.1

TableRange — Represents a Range of Cells (Maybe One Cell)

Note: Unlike Microsoft Excel, TablePage doesn't support the TableRange interface.

  • Value

    You can place a single value or an array here. These values will be placed to the range's coordinates. Values, which are out of range, will be silently ignored.

  • CreateArray, this[int,int], FlushArray:

    CreateArray creates an inner array of the range's size of the type, which can be directly understood by table processor (uno.Any for OOo and object for Excel).
    this[int,int] enables your interaction with the array created. Here indexes start from 0 and are relative to upper-left corner of the range. It's like with the usual array, which knows nothing about the range it will be placed to.
    The FlushArray method transfers the data from the inner array, created with CreateArray, to the table processor.

TableDiagram — Represents a Chart. New interface in v1.1

  • Name, XAxisName, YAxisName

    Names of the diagram, X, Y axis.

  • DrawRect

    Chart position rectangle.

  • XAxisNamesRange

    Sets a range, which gives names to items on X axis. The values from the range are copied.

  • SetMainAxisNamesRange

    Sets a range, which gives names to items (columns, etc.). The values from the range are copied.

  • MainAxisNames

    Same as above, but works with a string array, not range.

  • MoveToRectOf

    Moves chart to the rectangle of the given TableRange (gets range's coordinates and uses DrawRect mutator).

Implementation Comments

  • The effect of double TableRange.ColumnWidth may vary from Excel to OOo, because I don't know what double means for both. But this property is still valuable if you need to make all the columns as wide as a particular one after auto-sizing.
  • I didn't do any experiments with border color parameter (int color) in TableRange.BorderAround. I always use 0, and it gives me black. Maybe there's a way to use ColorIndexes conversion from the ConstConvert class somehow.
  • /* For Excel programmers */ Yes, I have no Font class. I don't need so many font properties and I decided to implement valuable parts of its functionality in Range classes.

Excel Specific

  • Excel likes color indexes and dislikes RGB. So RGB values like FontColor and BackgroundColor are converted to the nearest color, understood by Excel. For details see ConstConvert class.
  • ExcelApp.Workbook, ExcelSheet.Worksheet, ExcelRange.Range and ExcelDiagram.Chart properties give you raw access to Excel.
  • I don't use Microsoft custom Excel wrapper (as warning suggests) since I had some problems with it while deploying software on some machines. I suppose there's a checkbox in Microsoft Office's installation, which installs custom wrappers, and by default the checkbox is off. Anyway, my method works :-)

OpenOffice Calc Specific

  • OpenOffice likes RBG colors and knows nothing about color indexes. ColorIndexes for OpenOffice are converted to the corresponding RGB colors (great thanks for authors of Color Palette and the 56 Excel ColorIndex Colors)
  • OpenOffice supports no line styles (except for double lines). So line styles are NOT SUPPPORTED for OO implementation.
  • OpenOffice dislikes a lack of values (when the array is smaller than the range) for AddArray, etc., but this is fixed in the wrapper.
  • OpenOffice doesn't know what a "decimal" data type is, has his own strange DateTime type (I can't make OO accept the value of its own DateTime type) and doesn't like bool values. So values of these types are hard-code-converted for OOo. See OORange.Conv method in the sources for details.
  • OpenOffice cross-platform design makes use of the uno.Any data type to communicate with the outer world (something like VARIANT I suppose). That's why while using OORange.Value — the array or value is COPIED ELEMENT BY ELEMENT to the array of uno.Any objects. To avoid this, consider using TableRange.CreateArray and TableRange.FlushArray, it should work faster.
  • OOApp.XSpreadsheetDocument gives you low-level OpenOffice Calc access. So does OOSheet.XSpreadsheet, OORange.XCellRange and OODiagram.XChartDocument
  • User NumberFormats in OOo should be created in some number format storage for each document, but a particular format can be created only once for a document. So references for those formats are stored in OOApp.numberFormats (of course private).
  • FitToPagesWide and FitToPagesTall (size decreasing to fit to the desired number of pages) IS NOT IMPLEMENTED for OOo.
  • AddPageNumbering IS NOT IMPLEMENTED, because this is a default OOo behaviour.
  • Each OOSheet has a reference to its OOApp, because I can't find the way to get the XSpreadsheetDocument reference via XSpreadsheet correctly (not by name, etc), and I need the document reference to work with number formats.
  • OpenOffice 3.0 support is added as described here. To use OpenOffice 2.x, you should remove all cli_*.dll references from the project and reference cli_*.dll from program/assembly folder inside the OpenOffice 2.x installation folder. If using OpenOffice 2.x, you can comment out OOApp.ConfigureOO3x() call from OOApp constructor.
  • OpenOffice 3.0 DLLs, used in the sources, are extracted from the openofficeorg1.cab file. They shouldn't be distributed with the tblproc.dll, since OpenOffice installs them in the GAC.

Build Requirements

  1. .NET 2.0
  2. Visual Studio 2005
  3. OpenOffice.org 3.0 (maybe later versions will be compatible) and/or Microsoft Office XP or later. Not tested with Microsoft Office 2007.
  4. You need to reference Microsoft.Office.Core and Microsoft Excel Object library.
  5. You need to reference 6 OpenOffice .NET DLLs (cli_basetypes.dll, cli_cppuihelper.dll, cli_oootypes.dll, cli_uno.dll, cli_ure.dll, cli_uretypes.dll. I extracted them from OO installation .cab file, but they should reside in GAC after installation.
  6. In client code, you need to reference only tblProc.dll, but you'll need to have referenced Microsoft DLLs in application folder. You shouldn't copy OO DLLs to app folder, since there can be newer versions in GAC.

I tested all the stuff using Visual Studio 2005, Microsoft Office 2003, OpenOffice.org 3.0, Windows XP SP3.

Sample Code Discussion

It's quite easy. The grid on the form uses the custom DataSet, based on DataClass class. The TableProcessor combo on the toolbar allows you to select the type of the table processor. The Export button just sends the contents of grid to the processor (using a handy Export class — I use it frequently).

The "Create some colorized test doc" button runs the code, which tries to show most of valuable features.

Links

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author

Aleksandr Sazonov
Software Developer (Senior)
Russian Federation Russian Federation
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
BugCompatibility with OO 3.4 and Excel 2010 [modified]memberTeoMan1 Oct '12 - 22:39 
Thanks a lot.
I was using this component for exporting to OO version 3.2 and Excel 2003
 
Now:
I recompiled with OO version 3.4 and I have errors exporting to v 3.2
anyway I was not able and I am not able to export to Excel 2010
 
Does someone have a hint?

modified 9 Oct '12 - 10:33.

QuestionAdd two colours within the same cell...???membernirmalsat30 Jul '12 - 23:45 
Hi ,
 
I would like to know if its possible to add two different fonts with two different colours within the same cell..?
 
If it can be done can you please explain it.
 
Thanks,
Nirmal
QuestionSet Color to individual cellmembernirmalsat26 Jul '12 - 3:03 
Hi ,
 
I would like to know if its possible to set the background colour and font colour to individual cells.
 
Thanks in Advance..
QuestionPlease...convert to vb2005memberasep8522 Oct '11 - 15:42 
Nice....
But, i have problem with source code.
I dont understand with C.
Can you help me to convert the source code to visual basic language ?
 
Thanks
 
Asep
QuestionHow to SaveCopyAs for file excel to folder using TblProcmemberhungnguyen100419 Jul '11 - 17:13 
Hi Aleksandr Sazonov and Everybody,
I use project TblProc for export data to file excel and OO in my company.I don't know how to save or SaveCopyAs to folder after i have been data in TableSheet,TableRange(var "page,data" in project TblProc).I want to save to file in folder after open this file beacause i use ASP.NET. You can help me this problem. Thanks so much.
QuestionHow to use TblProc in asp.netmemberhungnguyen100418 Jul '11 - 21:38 
Hi Aleksandr Sazonov,
the present I use TblProc.Dll in asp.net so that export data to Msexcle. when I run visual studio 2010 then export is successful.But i public for web to a server then not export. You can help me this problem. Thanks so much.
 
NH
GeneralOOSheet: Paste from clipboardmemberFax6917 Jun '09 - 2:28 
Hi Aleksandr, you did a great job with this article. Do you know by chance how to paste anything from clipboard on a cell or range? I'm using an existing Calc file as a template. I tried to work like in Excel, sheet.Paste(), writing this with no success:
 
On OOSheet
 
public override void Paste(object destination, object link)
{
unoidl.com.sun.star.uno.XComponentContext localContext =
uno.util.Bootstrap.bootstrap();
XMultiComponentFactory multiComponentFactory = (XMultiComponentFactory)
localContext.getServiceManager();
XDispatchHelper dispatchHelper = (XDispatchHelper)
multiComponentFactory.createInstanceWithContext
("com.sun.star.frame.DispatchHelper", localContext);
XFrame frame = _app.GetFrame();
dispatchHelper.executeDispatch((XDispatchProvider)frame, ".uno:Paste", "", 0,
new unoidl.com.sun.star.beans.PropertyValue[0]);
}
 
On OOApp
 
public XFrame GetFrame()
{
XFrame frame = ((XModel)_Xdoc).getCurrentController().getFrame();
return frame;
}
 
I think I need to cast "destination" parameter to XFrame, but this
 
OOSheet d1 = ((OORange)destination).Page;
XFrame frame = ((XModel)d1).getCurrentController().getFrame();
 
generates a casting exception...
 
Any idea?
GeneralRe: OOSheet: Paste from clipboardmemberAleksandr Sazonov22 Jun '09 - 10:59 
Unfortunately no ideas. As OO contains other apps, not only calc, and the apps should have similar structure, maybe OO Write forums search can help you investigate the issue?
GeneralRe: OOSheet: Paste from clipboardmemberFax6923 Jun '09 - 2:11 
I tried to search for documentation but it's really poor... the aim was to paste the image of a generated barcode. I work-arounded by generating the full barcode string and using a barcode font, but I will face again the problem when I'll need to paste an image from clipboard.
Thanks anyway (still a great job! Smile | :) )
QuestionHow to update already opened OOo spreadsheet?memberMirceaNemteanu14 May '09 - 13:20 
Hi Aleksandr,
Thanks for your work and examples with OOo and C#. I would appreciate if you have any advice for the following scenario. The user opens an OOo calc spreadsheet, clicks a button that runs a macro. The macro calls an .exe (C#) that grabs data from a sql server and updates the same document that called it. My question is how would I get a reference in the C# to the already opened spreadsheet document? I need to update that spreadsheet in the background without closing, reopen it, so the user experience is just a button click that produces some visible updates.
Best regards,
Mircea
AnswerRe: How to update already opened OOo spreadsheet?memberAleksandr Sazonov19 May '09 - 6:25 
Sorry, I did no investigation how to deal with already opened documents. But if the opporyunity to connect to an open document exists, it should be shomewhere near Application object.
QuestionExcell and OOo Calc calculations and cell namesmemberanton.valter2 Mar '09 - 1:35 
Hello
 
How can i set name of the cell? and get cell from the sheet by cell name.
And how i can start calculation of the formula in the cell?
 
Thank.
AnswerRe: Excell and OOo Calc calculations and cell namesmemberAleksandr Sazonov2 Mar '09 - 3:58 
Sorry, no ideas now. I don't even know what a "cell name" is. I couldn't find good documentation on OOo Calc automation. So I can just describe methods of gaining info about OOO Calc automation internals^
 
1. As in Excel - record a macro taking actions you need to perform programmatically. If you're lucky, the macro code will contain the code you need - just translate it to C#.
 
2. Use SA.TblProc.OOEP class (in OOEP.cs file) to view the content of XPropertySet in runtime. There's usually a lot of interesting stuff inside. To use the class write something like
 
OOEP.Obj=(XPropertySet)cell;
 
in you code, place a breakpoint to the line
 
val = xps.getPropertyValue(name).Value;//OOEP.cs
 
and execute your code in DEBUG mode (with debug TblProc.dll version of course).
QuestionProblem while exporting file with deployed codememberPawanGuru6 Feb '09 - 22:44 
Hi Alexandr,
 
First Thanks for this demanding article.
 
My Question is- when run this code in debug mode and do export, It exporting file. But when I deployed it and run the application it not exporting OpenOffice file.
 
I referenced the files in my project given by u.
using ASP.Net 2,0. OO 3.0.
 
If missing something then please tell the steps of adding files and setting permission.
 
Thanks & Regds,
Pawan Kumar
AnswerRe: Problem while exporting file with deployed codememberAleksandr Sazonov7 Feb '09 - 22:58 
>But when I deployed it and run the application it not exporting OpenOffice file.
1. Any errors, exceptions?
2. You deployed what - I guess you deployed your own project, which uses TblProc.dll. If I'm right, maybe you can show a piece of of code, which exports data? Or you just deploy the sample?
3. You deployed it where? Is it a network share? Default .NET security policy rejects many operations if the binaries reside on a network share - in such a case you need to sign the code and configure .NET permissions.
GeneralRe: Problem while exporting file with deployed codememberPawanGuru12 Feb '09 - 22:05 
(A) When Application run in VS.net (Server) Environment and produce oo report. It producing Open Office Excel file and Charts. Its OK.
(B) In IIS Server it not produce the file and processing goes endless. Not produce any error / exception.
 
(C) When wait long for localhost it shows
 
"An un handeled exception(System.CannotUnloadAppDomainException) occured in aspnet_wp.exp"
======================================================================
What I have done. Open Office 3.0.
 
1. Added the TblProc.dll as reference in my project.
 
2. five cli_ files are in GAC
Excluding cli_uno.dll file.
 
give HResult error when add cli_uno.dll as reference so not added in project and it is not
 
in GAC and in VS Server without it producing file.
----------------------------------------------------------------------
GeneralRe: Problem while exporting file with deployed codememberAleksandr Sazonov16 Feb '09 - 0:30 
Sorry, I have no experience in ASP.net Frown | :-(
GeneralRe: Problem while exporting file with deployed codememberPawanGuru16 Feb '09 - 0:49 
Thanks dear for reply.
 
I appritiate u for coordination.
 
I will do some more search to find out the solution.
 
Regds
Pawan Kumar OMG | :OMG:
GeneralTblProc supports OpenOffice 2.x, not 3.xmemberAlexandr Sazonov26 Jan '09 - 2:34 
I plan to publish update when I'll migrate to OO 3.x
The main difference should be the way how app runs OO. + library references should be updated (AFAIK).
GeneralRe: TblProc supports OpenOffice 2.x, not 3.xmemberAlexandr Sazonov29 Jan '09 - 11:50 
OK, here's an update of the article. Now the code supports OOo 3.0, not 2.x. I made no tests, but doubtfully it is still compatible with 2.x. Anyway, minor changes can bring it back to support OOo 2.x (and discard compatibility with 3.0 for sure): re-reference .DLLs and, optionally, comment out 1 line in OOApp.cs. Anyway, if this version is not compatible with 2.x, I have no ideas how to make it work with both - 2.x and 3.0.
QuestionZIP file not recognizedmemberIntuition844 Dec '08 - 12:07 
Alexandr,
 
Your solution is exactly what I need, but I downloaded the zip files and they won't open. I'm using WinZip 12 which is the latest version. Has anyone else had this problem?
 
Thanks,
James
Questionhow to insert Columns Number in OpenOfficememberhungadam19 May '08 - 22:43 
hi Alexander,
thank you very much for teach me do title in OpenOffice i have done yet. but i have a question other have you help me.I want insert colum ID in OpenOffice not do in datagird.ex: ID Name Address City
1 adam PA PA
2 smith NW NW
3 Alice Mexico MX
.. ..................
 
column ID which i insert such as ex.thank you
AnswerRe: how to insert Columns Number in OpenOfficememberAlexandr Sazonov5 Jun '08 - 1:50 
Exporting data from DataGridView is not the only way for creating a report. For example, you can write your code to export the whole datasource to OO. You can get a TableRange object and set it's cells values using an array.
For example (assuming you have a TablePage page object;

object[,] arr=new object[10,4];
arr[0,0]=1;
arr[0,1]="adam";
arr[0,2]="NW";
arr[0,3]="MX";
//.... and so on. You can fill an array in for or foreach cycle
TableRange rng=page.Range(1,1,10,4); //example coordinates. the first column has #1, the last - #4, so 4 columns
rng.Value=arr;

Or you can get ranges for each cell/row and fill their values. Example:

TableRange rng=page.Range(2,2,2,2);
rng.Value="Hello!";

I didn't test the code, but it should be something like that. You can examine the export code used in the sample to export DataGridView's data to see the third way for exporting data. It's similar to the first way I've shown above, but it uses an "internal" array in the TableRange object to simplify data conversion:

TableRange data = page.Range(page.CurrentRow, 1, page.CurrentRow + nStrings-1, nVisibleCols);
data.CreateArray();
//...filling the array created in TableRange object
//and now put the data to OO (or Excel, it depends on the actual type of page object)
data.FlushArray();

GeneralExport data to OpenOffice by C#memberhungadam11 May '08 - 22:51 
hi Alexander,
i want to do report for my company as use OpenOffice Calc.but i don't know how to insert header in OpenOffice for report ex:"BAO CAO KET QUA TTHUE NHA";month:"2008";Location:"HCM CITY".i have done load data from dataset in OO as souce code of you but i haven't done discription as top.i have to you help me to do it.thank you very much
GeneralRe: Export data to OpenOffice by C#memberAlexandr Sazonov12 May '08 - 5:47 
If you're talking about changing document's properties (such as title, topic, etc., which are under "File->Properties..." menu item) - I don't know how to do it, never thout it can be useful.
Adding a title to the document's content should be quite easy. Assuming you have a sheet - a TableSheet object (in your case it will really be a OOSheet object). To get a TableSheet object you have to get an application object, using TableProcessor's factory methods and then create a sheet using LastPage or CreateNextPage method.
I usually add a header like that:

TableRange header=sheet.Range(sheet.CurrentRow,1,sheet.CurrentRow, nColumns);//nColumns-number of used columns
header.Merge();
header.Value="THE TEXT OF THE TITLE";
header.HAlign=HAlign.Center;
//other header text decoration using "header" varialbe
sheet.PrintRowsOnEachPage(sheet.CurrentRow,sheet.CurrentRow);//every printed page will contain the header
sheet.CurrentRow++;//to use AddArray correctly with other code

I made no tests nor compilation of the code above, but I hope it's really close to what you need

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 29 Jan 2009
Article Copyright 2007 by Aleksandr Sazonov
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid