Quantcast
Channel: Open XML Format SDK forum
Viewing all 1288 articles
Browse latest View live

Server end using OpenXML to generate Word doc:Target Invocation Exception -> Null argument

$
0
0

Our production server managed to reach a state in which OpenXML document modification wouldn't work anymore. The stack trace from the event log looks like this:


Timestamp: 25/03/2015 05:48:27

1 : Exception has been thrown by the target of an invocation: at blahblahblah.CreateDocumentsFromTemplate(DocumentTemplateData[] data, Int32 templateID, blah blah) in c:\Build\blah.cs:line 1212

2 : Exception has been thrown by the target of an invocation: at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)

at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)

at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)

at System.Activator.CreateInstance[T]()

at DocumentFormat.OpenXml.Packaging.OpenXmlPart.LoadDomTree[T()]

at DocumentFormat.OpenXml.Packaging.MainDocumentPart.get_Document()

at blahblah.OpenXMLRenderer.GetWordReport(String filename, DataSet dataset, Dictionary`2 values, List`1 img) in c:\Build\blah.cs:line 297

at blah.DocumentFromTemplate.Render(Int32 letterID, String[] list, DataSet documentTables, Int32 officeID, List`1 img, Int32 orgUnit, Int32 fileID) in c:\Build\blah.cs:line 172

at blah.CreateDocumentsFromTemplate(DocumentTemplateData[] data, Int32 templateID, blah blah) in c:\Build\blah.cs:line 1072

3 : Value cannot be null

Parameter name: key :    at System.Xml.NameTable.Add(String key)

   at DocumentFormat.OpenXml.OpenXmlElementContext.Init()

   at DocumentFormat.OpenXml.OpenXmlPartRootElement..ctor()


As far as I can see, the explanation is like this:

There's a constructor being called by reflection – OpenXmlPartRootElement() – which is in turn calling System.XmlNameTable.Add(key) with a null value for key.

Using Reflector, we can see that the constructor being called is actually the base constructor forDocumentFormat.OpenXml.Wordprocessing.Document– its base type is OpenXmlPartRootElement. Its constructor is calling in turn the constructor for OpenXmlElementContext in order toinitialize its member variable. Inside this constructor – in a call to the method OpenXmlElementContext.Init()– was the ArgumentNullException from calling NameTable.Add.

Here is the reflected code (using ILSpy) for Init():

// DocumentFormat.OpenXml.OpenXmlElementContext

private void Init(){

    for (int i = 1; i < NamespaceIdMap.Count; i++)    {        this._xmlNameTable.Add(NamespaceIdMap.GetNamespaceUri((byte)i));

    }

    this._xmlNameTable.Add("http://www.w3.org/2000/xmlns/");

    this.XmlReaderSettings = new XmlReaderSettings();

    this.XmlReaderSettings.NameTable = this.XmlNameTable;

    this.XmlReaderSettings.IgnoreWhitespace = true;

}

As seen here, there are two calls to NameTable.Add: one inside a for loop, and one with a string constant. We can rule out the string constant – it will never be null.

Inside the loop, we run through the numbers 1 to the Count property of NamespaceIdMap. For each of these, we retrieve the value of GetNamespaceUri(i).

Inlining the code called by GetNamespaceUri, we have the following:

// DocumentFormat.OpenXml.NamespaceIdMap

 

private static string[] _namespaceList = new string[]{    "",      "http://www.w3.org/XML/1998/namespace",     "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",     "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",     "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties",     "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes",     "http://purl.org/dc/elements/1.1/", 

   // … many more like this

}

private static XmlNamespaceManager _xmlNamespaceManager;

private static object[] _namespaceObjectList;

public static string GetNamespaceUri(byte namespaceId){

   //inlined: call to static method NamespaceIdMap.MakeSureInitialized();

    if (NamespaceIdMap._xmlNamespaceManager == null)    {

        XmlNamespaceManager xmlNamespaceManager =  new XmlNamespaceManager(NamespaceIdMap.GlobalNamespaceNameTable);

        object[] array = new object[NamespaceIdMap._namespaceList.Length];

        for (int i = 0; i < NamespaceIdMap._namespaceList.Length; i++)        {            xmlNamespaceManager.AddNamespace(NamespaceIdMap._namespacePrefixList[i], NamespaceIdMap._namespaceList[i]);

           object obj = NamespaceIdMap.GlobalNamespaceNameTable.Get(NamespaceIdMap._namespaceList[i]);

            array[i] = obj;

        }

        NamespaceIdMap._xmlNamespaceManager = xmlNamespaceManager;

        NamespaceIdMap._namespaceObjectList = array;    

}

    //end inlined

    return (string)NamespaceIdMap._namespaceObjectList[(int)namespaceId];

}

Here we see used the non-const, non-readonly static fields _xmlNamespaceManager, _namespaceObjectList, and the static property GlobalNamespaceNameTable that essentially wraps yet another static member (though of a different class).

No locking is used in any part of the library that we examined in ILSpy.

It is conceivable that at some point, a race condition in the OpenXml library caused any one of these values to be corrupted, leading to one or more null entries in the _namespaceObjectList array.

Evidence of this: when the server was restarted, the issue did not recur.

Is there a known fix for this, or some configuration we could do to prevent this from happening?


Detect tables in a spreadsheet?

$
0
0

Hi all,

I'm looking for way to detect a table in the spreadsheet. I know there's a way to get it through the SDK, but it only works for those tables which were inserted and defined as a table (TableDefinitionParts? or getTables() in POI). However, it doesnt work for those table which were constructed manually, by entering column names, headers, changing styles, entering data etc

any ideas how to achieve this? any algorithms/sample code/SDK you can lead me to? 

thanks

Lior

To Unprotect the word document using Open XML

$
0
0

Hi,

I am trying
to unprotect the word document using open xml. I am trying to get hash value
generated while protecting the document and then comparing it. But generated
hash values are always different. Please let me know the algorithm to generate
the hash value to unprotect the word document.<o:p></o:p>

Is there any
other way to achieve this functionality.

Thanks

how to retrieve parts of my Excel document ?

$
0
0

Hello,

1/ What is the difference between these openxml methods please : descendants() elements() getfirstchild() childelements() ?

2/ I create an excel from scratch programmatically. Some of these methods above return only the customized parts. If I want to change the width of a column from the default value for instance, I have to specifically create this column, and then it will be the only one I manage to retrieve using one of the methods above. But when I open my exel document, I have all my other default columns with their content, so there must be a way to retrieve them as well while I am creating my document, how can I do that please?

Regards,

Julien

Auto fit columns in excel using open xml

$
0
0

I have generate excel using open xml and it contain auto fit property for columns. my problem is that the excel is opening very well in kingsoft spreadsheets and other tools, but not opening in microsoft excel 2013 and older version. Is there any solution for auto fit columns in excel using open xml and should open in Microsoft excel  all version

OpenXML Excel file, works in Excel 2007, OpenOffice, etc but not in Excel 2010

$
0
0

Hi everyone,

I have a problem.  I host a free website, sharing source code and ideas with other developers.  One of my projects is a very simple C# class, which generates an Excel 2007 .xlsx file.  All source code is provided, along with a demo showing how to use it, free of charge.  No registration required.

http://www.mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm

The .xlsx files that this class generates are fine, they open in Excel 2007 & OpenOffice, I've run the OpenXmlValidatoron the files, and there are no reported problems.

However, If I open the file in Excel 2010 (with SP1), it opens, but if I go to the Print or Print Preview screen, Excel 2010 crashes.  

Googling around, I've found that many many users have experienced problems with HP print drivers, I followed some suggestions, such as turning off multi-threading in Excel, but it makes no difference.  I tried setting the default printer as the "Microsoft XPS Document Writer", but it made no difference.

Here is a copy of the Excel file that my demo produces (and which crashes Excel 2010).   Can someone tell me why it opens okay, but then crashes Excel 2010 ?  

http://www.MikesKnowledgeBase.com/SampleCode/Sample.xlsx

I can get around the problem by loading this file in Excel 2010, saving it as an ".xls" file (!!) and re-loading that... but it kinda defeats the purpose.

And, more generally, why does Excel 2007, OpenOffice and the OpenXmlValidator consider it to be in the correct format, but it crashes Excel 2010 ?  I'm surprised that Excel 2010 doesn't at least attempt to report some kind of problem with the Excel file, rather than bombing out.

Mike


Apply MS Style to a table

$
0
0

Hi.

I currently coding on a template which use openXML. I create some tables and I would like apply to them a MS style. I saw in style.xml some values about those default style but when I try to apply it to my tables it doesn't work.

Specifically, I would like apply the "Medium Grid 1 Accent 1" to my tables.

Here my code :

//init code vTable = new Table(); vProps = new TableProperties(); vTable.AppendChild<TableProperties>(vProps); ApplyMsStyleToTable(vTable, -1, "Medium Grid 1 Accent 1"); //fill table //------------------------------------------------------- private static void ApplyMsStyleToTable(Table pTable, int pIndex, string pStyleMS) { try { TableProperties vTblPr = pTable.Descendants<TableProperties>().FirstOrDefault(); if(pIndex < 0) vTblPr.AppendChild<TableStyle>(new TableStyle {Val = pStyleMS}); else vTblPr.InsertAt(new TableStyle { Val = pStyleMS }, pIndex); } catch (Exception) { throw; } }

So, can I use MS default style or I must made it by myself ? If I must made it, where can I find all informations to create the exact same style ?

I have another question about this, if I can use MS default style, does the needed string must be in the current word language ? I want to say, if my word is in another language than english does the "Medium Grid 1 Accent 1" string works in a French or Korean word  ?

Thank you in advance for your help.

EDIT : I'm using word 2007

PS : sorry for my bad english ;).


Merged documents openxml mailmerge

$
0
0

I am a chemistry graduate and very new to programming, having learned everything from the Internet. I have a Word document with mail merge fields. The data source is an Excel file. I want to change the datasource Excel file dynamically and save the the merged document in a new file.

public static void mergeDocs() {
    string fileToOpen = @"D:\CSharpProjects\MailMerge\document.docx";
    using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(fileToOpen, true))
    {
        int mailmergecount = wordDocument.MainDocumentPart.DocumentSettingsPart.Settings.Elements<MailMerge>().Count();
        Console.WriteLine ("Number of mail merges:{0}",  mailmergecount);
        MailMerge mymerge = wordDocument.MainDocumentPart.DocumentSettingsPart.Settings.Elements<MailMerge>().First();
        mymerge.ConnectString.Val = "Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=D:\\CSharpProjects\\MailMerge\\Data.xlsx;Mode=Read;Extended Properties=\"HDR=YES;IMEX=1;\";Jet OLEDB:System database=\"\";Jet OLEDB:Registry Path=\"\";Jet OLEDB:Engine Type=37;Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password=\"\";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don\'t Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False";
        foreach
        (var relationship in wordDocument.ExternalRelationships.Where(Rel =>
        Rel.RelationshipType == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/mailMergeSource"))
        { wordDocument.DeleteExternalRelationship(relationship); }
        string DataPath = @"D:\CSharpProjects\MailMerge\data1.xlsx";
        var dsRelationship = wordDocument.MainDocumentPart.DocumentSettingsPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/mailMergeSource", new Uri(string.Format("file:///{0}", DataPath)));
        mymerge.DataSourceReference.Id = dsRelationship.Id;
        mymerge.ViewMergedData.Val = true;
    }

This changes the datasource, but I need to manually finish the merge and save the merged document. How do I automate this process?


Adding .ODC location to Excel file(not the actual conneciton string)

$
0
0

Hello! I have a problem with OpenXML, Let me try to clearify:

1. I have a local .xlsx file on a server, this file will eventually contain a pivot table or a powerBI report or something that needs a dataconnection;

2. I have a SharePoint Online environment(office 365), in this environment is an .odc file present;

3. Serverside code needs to add an reference string, like (Root/trusted connections/MyConnection.odc) to the local .xlsx file;

4. When the .xlsx file is uploaded to SharePoint it automatically needs to refresh data from the .odc that was present before my .xlsx was uploaded. (So i am not looking for ways to refresh data, i just need to know how to add the odc file path. I hope my question belongs here) I am using OpenOffice SDK, because the application will be server-side:

Code i am trying now:

 using (SpreadsheetDocument spreadSheet= SpreadsheetDocument.Open(TempFilePath, true))
                { 
                        WorkbookPart workbookPart = spreadSheet.WorkbookPart;
                        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
                        

                        Connection Conec = new Connection();
                        Conec.ConnectionFile = "C:\\Connectionsfiles\\Testing\\TryMe.odc";
                        Conec.Name = "Testing a Dataconnection";
                        Conec.OnlyUseConnectionFile = true;
                        Conec.RefreshOnLoad = true;
                
 
                        //add this connection to the .xlsx file and save it. Conec.ConnectionFile will be changed      with   a SharePoint Online path later
                    }

But i'm stuck now, any ideas?

When reading the Rich Text present in Excel column using open XML its taking it as plain text

$
0
0

When i am reading excel columns using open Xml in C# everything is working fine except the column that contain Rich Text (ex: bold, italic,color,size). Its reading the Rich Text content as plain text. As we know for Rich Text in open XML we get the text as Runs (C# object) which contains the text as value and rpr as run properties. I have also written the code to convert Runs to html. But the issue is that for some Rich Text format its reading it as Runs but most of the Rich Text its reading it as plain text.

Merging PowerPoint decks using OpenXML SDK

$
0
0
I want to merge multiple PointPoint decks, the merging works fine when every deck contains 30 or less slides, If any deck contains more than 30 slides, PowerPoint issues a Repair message. OpenXML SDK tool validation is not helping, I'm using the following code to do merging, or any other library that will help? I need this to be done immediately, Please help.

    public class SlideMerger
    {
 
        #region variables
 
        uint uniqueId;
        int partId = 0;        
        List<string> mergingParts = new List<string>() { "introPart" ,"productsPart", "priceGridsPart", "closingPart", "contactPart" };
 
        #endregion
 
        #region methods
 
        public void MergeSlides(List<MemoryStream> sourceDecks, MemoryStream destDeck)
        {
 
            foreach (var sourcePresentation in sourceDecks)
            {
                MergeSlides(sourcePresentation, destDeck);
                partId++;
            }
        }
 
        void MergeSlides(MemoryStream sourcePresentation, MemoryStream destPresentation)
        {
            int id = 0;
 
            // Open the destination presentation.
            using (PresentationDocument DestDeck = PresentationDocument.Open(destPresentation, true))
            {
                PresentationPart destPresPart = DestDeck.PresentationPart;
 
                // If the merged presentation doesn't have a SlideIdList element yet then add it.
                if (destPresPart.Presentation.SlideIdList == null)
                    destPresPart.Presentation.SlideIdList = new SlideIdList();
 
                // Open the source presentation. This will throw an exception if the source presentation does not exist.
                using (PresentationDocument SourceDeck = PresentationDocument.Open(sourcePresentation, false))
                {
                    PresentationPart sourcePresPart = SourceDeck.PresentationPart;
 
                    // Get unique ids for the slide master and slide lists for use later.
                    uniqueId = GetMaxSlideMasterId(destPresPart.Presentation.SlideMasterIdList);
                    uint maxSlideId = GetMaxSlideId(destPresPart.Presentation.SlideIdList);
 
                    // Copy each slide in the source presentation in order to the destination presentation.
                    foreach (SlideId slideId in sourcePresPart.Presentation.SlideIdList)
                    {
                        SlidePart sp;
                        SlidePart destSp;
                        SlideMasterPart destMasterPart;
                        string relId;
                        SlideMasterId newSlideMasterId;
                        SlideId newSlideId;
 
                        // Create a unique relationship id.
                        id++;
                        sp = (SlidePart)sourcePresPart.GetPartById(slideId.RelationshipId);
                        relId = mergingParts[partId] + id;
 
                        // Add the slide part to the destination presentation.
                        destSp = destPresPart.AddPart<SlidePart>(sp, relId);
 
                        // The master part was added. Make sure the relationship is in place.
                        destMasterPart = destSp.SlideLayoutPart.SlideMasterPart;
                        destPresPart.AddPart(destMasterPart);
 
                        // Add slide master to slide master list.
                        uniqueId++;
                        newSlideMasterId = new SlideMasterId();
                        newSlideMasterId.RelationshipId = destPresPart.GetIdOfPart(destMasterPart);
                        newSlideMasterId.Id = uniqueId;
 
                        // Add slide to slide list.
                        maxSlideId++;
                        newSlideId = new SlideId();
                        newSlideId.RelationshipId = relId;
                        newSlideId.Id = maxSlideId;
 
                        destPresPart.Presentation.SlideMasterIdList.Append(newSlideMasterId);
                        destPresPart.Presentation.SlideIdList.Append(newSlideId);
                    }
 
                    // Make sure all slide ids are unique.
                    FixSlideLayoutIds(destPresPart);
                }
 
                // Save the changes to the destination deck.
                destPresPart.Presentation.Save();
            }
        }
 
        void FixSlideLayoutIds(PresentationPart presPart)
        {
            // Make sure all slide layouts have unique ids.
            foreach (SlideMasterPart slideMasterPart in presPart.SlideMasterParts)
            {
                foreach (SlideLayoutId slideLayoutId in slideMasterPart.SlideMaster.SlideLayoutIdList)
                {
                    uniqueId++;
                    slideLayoutId.Id = (uint)uniqueId;
                }
 
                slideMasterPart.SlideMaster.Save();
            }
        }
 
        uint GetMaxSlideId(SlideIdList slideIdList)
        {
            // Slide identifiers have a minimum value of greater than or equal to 256
            // and a maximum value of less than 2147483648.
            uint max = 256;
 
            if (slideIdList != null)
                // Get the maximum id value from the current set of children.
                foreach (SlideId child in slideIdList.Elements<SlideId>())
                {
                    uint id = child.Id;
 
                    if (id > max)
                        max = id;
                }
 
            return max;
        }
 
        uint GetMaxSlideMasterId(SlideMasterIdList slideMasterIdList)
        {
            // Slide master identifiers have a minimum value of greater than or equal to 2147483648.
            uint max = 2147483648;
 
            if (slideMasterIdList != null)
                // Get the maximum id value from the current set of children.
                foreach (SlideMasterId child in slideMasterIdList.Elements<SlideMasterId>())
                {
                    uint id = child.Id;
 
                    if (id > max)
                        max = id;
                }
 
            return max;
        }
 
        #endregion
    }

AliAmjad

How to create editable Chart in Wordprocessing document using Open Xml SDK in C#

$
0
0

I am able to create chart in Word document from scratch using Open XML SDK however, I am unable to edit the created chart data in word document manually. To edit a chart manually, when I right click on chart, word opens a right click menu. There after when I click Edit Data option, it does nothing. 

How can we embed the data with chart using open xml SDK so that it can be edited manually post document generation?

Please help.

how to merge up all the property that apply to one run?

$
0
0

Hi

I've read the reference :<<ECMA-376, Fourth Edition, Part 1 - Fundamentals And Markup Language Reference>>

in section 17.7.2 Style Hierarchy, it described the hierarchy of the style definition.

as the rules is complicated, I'm thinking is there any API have implemented this merge processing?

I want to retrieve exactly the styles(rPr,pPr...) apply to one paragraph or one run.

Is there any out-of-box API I can use?

what I need is like:

when I got the style define like this

<w:style w:styleId="Strong">
<w:basedOn w:val="Underline"/>

<w:rPr>
<w:b/>
</w:rPr>
</w:style>
<w:style w:styleId="Underline">
<w:basedOn w:val="Emphasis"/>

<w:rPr>
<w:u/>
</w:rPr>
</w:style>
<w:style w:styleId="Emphasis">

<w:rPr>
<w:i/>
</w:rPr>
</w:style>

the API function can give me a merged rpr,tell me the "strong" style is:

 Bold
 Underline (inherited from Underline)
 Italics (inherited from Emphasis)

and if the certain "run" got it's own style define, then merge it too.

thanks a lot!

Setting width of the sheet columns using open xml vb.net

$
0
0

I am writing a code to set the width of the excel sheet generated using open xml sdk 2.5 but not able to get it right. I am always getting the default width of the columns in the excel generated.

Here is the code snippet I am using

PrivateFunctionBuildAssumesSpreadsheet(ByValSourceDataAsSystem.Data.DataTable,ByValReportPathAsString)AsBoolean


       

' Create a spreadsheet document by supplying the filepath.


       

' By default, AutoSave = true, Editable = true, and Type = xlsx.


       

DimspreadsheetDocument__1AsSpreadsheetDocument = SpreadsheetDocument.Create(ReportPath, SpreadsheetDocumentType.Workbook)

       

' Add a WorkbookPart to the document.


       

DimworkbookpartAsWorkbookPart = spreadsheetDocument__1.AddWorkbookPart()

        workbookpart.Workbook =

NewWorkbook()

       

' Add a WorksheetPart to the WorkbookPart.


       

DimworksheetPartAsWorksheetPart = workbookpart.AddNewPart(OfWorksheetPart)()

        worksheetPart.Worksheet =

NewWorksheet(NewSheetData())

       

'Dim columns As New Columns


       

'columns.Append(getColumn(0, 3, 250.0))


       

'worksheetPart.Worksheet.AppendChild(getColumn(0, 3, 250.0))


       

' Add Sheets to the Workbook.


       

DimsheetsAsSheets = spreadsheetDocument__1.WorkbookPart.Workbook.AppendChild(OfSheets)(NewSheets())

       

' Append a new worksheet and associate it with the workbook.


       

DimsheetAsNewSheet()With{.Id = spreadsheetDocument__1.WorkbookPart.GetIdOfPart(worksheetPart), .SheetId = 1, .Name = "mySheet"}

        sheets.Append(sheet)

       

' Get the sheetData cell table.


       

DimsheetDataAsSheetData = worksheetPart.Worksheet.GetFirstChild(OfSheetData)()

        sheetData.AppendChild(getColumn(1, 3, 250.01))

     

       

' Setting the header colum for the sheet


       

DimheaderRowSheetAsNewRow

       

DimheaderRowData()AsString= {"HEADERINFO","MORTGAGEID","MESSAGE"}

       

DimrowData()AsString


        headerRowSheet = CreateContentRow(1, 3, headerRowData)

        sheetData.AppendChild(headerRowSheet)

       

DimiAsInteger


       

WithSourceData

           

Fori = 2To.Rows.Count - 1

               

DimcontentRowAsNewRow

                rowData = {.Rows(i).Item(

"headinginfo"), .Rows(i).Item("mortgageid"), .Rows(i).Item("message")}

                contentRow = CreateContentRow(i, 3, rowData)

                sheetData.AppendChild(contentRow)

               

' sheetData.AppendChild(getColumn(1, 3, 25000.0))


           

Next


       

EndWith


        spreadsheetDocument__1.Close()

       

ReturnTrue


 

=================================================================================

Setting column width here

===============================================================================

   

PublicFunctiongetColumn(startIndexAsInteger, endIndex AsInteger, width AsDouble)AsColumn

       

DimcolumnAsNewColumn

        column.Min = startIndex

        column.Max = endIndex

        column.Width = width

        column.CustomWidth =

True


        column.BestFit =

True


       

Returncolumn

   

EndFunction



End

Class

EndFunction

Solution: How to AutoFit Excel Content

$
0
0

I, like most, am new to Open XML.  I was trying to find a way to size the column to my largest item.  I mostly found that the current spec doesn't support it automatically.  After poking around I found a formula which I rework to calculate the width based on the pixel width of the string.  I then found a way to size the column.

Here is the complete source code to do it.  I should mention that I am NOT searching for the largest string in the column but rather calculating 1 item.  Haven't quite figured out how to do search yet.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace AutoFit
{
  class Program
  {
   static void Main(string[] args)
   {
     string docName = @"D:\Temp\MyFirstExcel.xlsx";

     // Create a Wordprocessing document.
     using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(docName, SpreadsheetDocumentType.Workbook))
     {
      // Add a WorkbookPart to the document.
      WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
      workbookpart.Workbook = new Workbook();

      // Add a WorksheetPart to the WorkbookPart.
      WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
      worksheetPart.Worksheet = new Worksheet();

      // ####################################
      //   IMPORTANT STUFF
      // ####################################

      string strText = "This is some really, really long text to display.";
      double width = GetWidth("Calibri", 11, strText);

      string strText2 = "123";
      double width2 = GetWidth("Calibri", 11, strText2);

      Columns columns = new Columns();
      columns.Append(CreateColumnData(2, 2, width));
      columns.Append(CreateColumnData(3, 3, width2));
      worksheetPart.Worksheet.Append(columns);

      // ####################################
      //   END OF IMPORTANT STUFF
      // ####################################

      SheetData sd = new SheetData();
      worksheetPart.Worksheet.Append(sd);

      // Add Sheets to the Workbook.
      Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());


      // Append a new worksheet and associate it with the workbook.
      Sheet sheet = new Sheet()
      {
        Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
        SheetId = 1,
        Name = "mySheet"
      };
      sheets.Append(sheet);



      // Add Data
      Row row = new Row();

      Cell cell;

      // String
      cell = CreateSpreadsheetCellIfNotExist(worksheetPart.Worksheet, "B2");
      cell.CellValue = new CellValue(strText);
      cell.DataType = CellValues.String;


      // Number
      int count = 123;
      cell = CreateSpreadsheetCellIfNotExist(worksheetPart.Worksheet, "C2");
      CellValue cellValue = new CellValue(count.ToString());
      cell.CellValue = cellValue;
      cell.DataType = CellValues.Number;

      workbookpart.Workbook.Save();

      // Close the document.
      spreadsheetDocument.Close();
     }
   }

   private static double GetWidth(string font, int fontSize, string text)
   {
     System.Drawing.Font stringFont = new System.Drawing.Font(font, fontSize);
     return GetWidth(stringFont, text);
   }

   private static double GetWidth(System.Drawing.Font stringFont, string text)
   {
     // This formula is based on this article plus a nudge ( + 0.2M )
     // http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.width.aspx
     // Truncate(((256 * Solve_For_This + Truncate(128 / 7)) / 256) * 7) = DeterminePixelsOfString

     Size textSize = TextRenderer.MeasureText(text, stringFont);
     double width = (double)(((textSize.Width / (double)7) * 256) - (128 / 7)) / 256;
     width = (double)decimal.Round((decimal)width + 0.2M, 2);

     return width;
   }

   private static Column CreateColumnData(UInt32 StartColumnIndex, UInt32 EndColumnIndex, double ColumnWidth)
   {
     Column column;
     column = new Column();
     column.Min = StartColumnIndex;
     column.Max = EndColumnIndex;
     column.Width = ColumnWidth;
     column.CustomWidth = true;
     return column;
   }

   // Given a Worksheet and a cell name, verifies that the specified cell exists.
   // If it does not exist, creates a new cell.
   private static Cell CreateSpreadsheetCellIfNotExist(Worksheet worksheet, string cellName)
   {
     string columnName = GetColumnName(cellName);
     uint rowIndex = GetRowIndex(cellName);

     IEnumerable<Row> rows = worksheet.Descendants<Row>().Where(r => r.RowIndex.Value == rowIndex);
     Cell cell;

     // If the Worksheet does not contain the specified row, create the specified row.
     // Create the specified cell in that row, and insert the row into the Worksheet.
     if (rows.Count() == 0)
     {
      Row row = new Row() { RowIndex = new UInt32Value(rowIndex) };
      cell = new Cell() { CellReference = new StringValue(cellName) };
      row.Append(cell);
      worksheet.Descendants<SheetData>().First().Append(row);
      worksheet.Save();
     }
     else
     {
      Row row = rows.First();

      IEnumerable<Cell> cells = row.Elements<Cell>().Where(c => c.CellReference.Value == cellName);

      // If the row does not contain the specified cell, create the specified cell.
      if (cells.Count() == 0)
      {
        cell = new Cell() { CellReference = new StringValue(cellName) };
        row.Append(cell);
        worksheet.Save();
      }
      else
        cell = cells.First();
     }

     return cell;
   }

   // Given a cell name, parses the specified cell to get the column name.
   private static string GetColumnName(string cellName)
   {
     // Create a regular expression to match the column name portion of the cell name.
     Regex regex = new Regex("[A-Za-z]+");
     Match match = regex.Match(cellName);

     return match.Value;
   }

   // Given a cell name, parses the specified cell to get the row index.
   private static uint GetRowIndex(string cellName)
   {
     // Create a regular expression to match the row index portion the cell name.
     Regex regex = new Regex(@"\d+");
     Match match = regex.Match(cellName);

     return uint.Parse(match.Value);
   }
  }
}

Merging sheets creates conflict when images exists on both sheets

$
0
0

Hi

I have a solution of creating and merging Excel-files in a webservice.

This has been working fine, until both of the Excel-files began to contain images.

As an example, the service recieves one Excel template and one Excel workbook.
The goal is to create a new Excel workbook consisting of the supplied parts.

Since the template is indeed a template (xltx), I start of by working with the workbook.
I then merge all worksheets from the template file to the workbook file.
This is done in memory with the help of EPPlus version 3.1.2 and the following routine where grmName is path to the template file and wbkName is path to the workbook:

Friend Sub XLAddInfoSheets(ByVal grmName As String, ByVal wbkName As String)

        Dim targetFI As New FileInfo(wbkName)
        Dim templateFile As String = grmName
        Dim ContentOverrides As New ArrayList

        Try
            Using t As New ExcelPackage
                Using Tstream As New FileStream(wbkName, FileMode.Open, FileAccess.ReadWrite)
                    t.Load(Tstream)
                End Using
                Using d As New ExcelPackage
                    Using Dstream As New FileStream(templateFile, FileMode.Open)
                        d.Load(Dstream)
                    End Using
                    For Each dws In d.Workbook.Worksheets
                        Dim addOK As Boolean = True
                        If dws.Name = "Försättsblad" Or dws.Name = "Cover Page" Then
                            Dim tmpName As String = dws.Name
                            For Each twx In t.Workbook.Worksheets
                                If LCase(twx.Name) = LCase(tmpName) Then
                                    addOK = False
                                    Exit For
                                End If
                            Next
                            If addOK Then
                                t.Workbook.Worksheets.Add(tmpName, dws)
                                t.Workbook.Worksheets(tmpName).Hidden = dws.Hidden
                            End If
                        End If
                    Next
                End Using

                t.SaveAs(targetFI)
            End Using
        Catch ex As Exception
            WriteLogg("Could not merge coverpages from the template.", ex.Message, logFile)
            Exit Sub
        End Try

    End Sub

When opening the created file (if both the template and the workbook contains images) shows a repairable error.
After the repair is made, the images in the inserted sheets is actually an image from the original workbook, not the same image as in the template sheet.
I realise that there is a mixup of relations causing this, so I tried looping through the images in the inserted sheets and delete the original image (DrawingPart) and add the image again.

This is done with the following code where wbPart is the actual Workbookpart and imagePath is path to the image which is extracted to disk earlier:

    Private Sub XLRelateImages(ByVal wbPart As WorksheetPart, ByVal imagePath As String)

        Try
            Dim drawingPart = wbPart.DrawingsPart
            If drawingPart IsNot Nothing Then
                Dim doc As New XmlDocument()
                doc.Load(drawingPart.GetStream())
                Dim ns As New XmlNamespaceManager(doc.NameTable)
                ns.AddNamespace("a", "http://schemas.openxmlformats.org/drawingml/2006/main")
                ns.AddNamespace("xdr", "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing")
                Dim list As XmlNodeList = doc.SelectNodes("/xdr:wsDr/xdr:twoCellAnchor/xdr:pic/xdr:blipFill/a:blip", ns)
                Dim pairList As New List(Of KeyValuePair(Of String, String))()
                For Each node As XmlNode In list
                    For Each attribute As XmlAttribute In node.Attributes
                        Dim pair As New KeyValuePair(Of String, String)(attribute.Value, attribute.Name)
                        pairList.Add(pair)
                    Next
                Next
                For Each image As KeyValuePair(Of String, String) In pairList
                    Dim id As String = image.Key
                    Dim name As String = image.Value
                    Dim oldPart As OpenXmlPart = Nothing
                    If name = "r:embed" Then
                        ' get ImagePart via id
                        oldPart = drawingPart.GetPartById(id)
                        ' delete ImagePart
                        drawingPart.DeletePart(oldPart)
                        ' add the ImagePart
                        Dim newPart As ImagePart = drawingPart.AddImagePart(ImagePartType.Png, id)
                        ' replace image
                        Dim replacement As String = imagePath
                        Using stream As New FileStream(replacement, FileMode.Open)
                            ' feed data to the newPart
                            newPart.FeedData(stream)
                        End Using
                    End If
                Next
                ' save xml document to the stream
                doc.Save(drawingPart.GetStream(FileMode.Create))
            End If
        Catch ex As Exception

        End Try

    End Sub

When I examine the result of this I still get the same error when I'm opening the file, but the correct image is now shown on the inserted sheets.

I believe there must be some other relation that is left in the workbook, but I have not been able to locate it.

Can someone help with sample code in VB or C# I would be much obliged?


Best Regards Peter Karlström Midrange AB, Sweden

What's happening when Word opens and saves a document?

$
0
0

Hello,

I got very unspecific question, but I don't know where to start. I have an open xml document which gets generated by a third party tool. If I open the document using open xml sdk it looks VERY different from how it looks like when I opened and saved it before using Word 2013.

I'm trying to get an understanding on whats Word doing! From what I've seen it's doing some remodelling on the xml file, since it looks very different (other and way more descendants than before) and I would like to achieve the same thing using open xml.

Although this might be already to much information: The generated word documents contains html code with links to pictures. After Word has touched the file the picture is inside a drawing element, before it's not but in Word both versions look the same.

I'm thankful for any help you can give me.

Cheers Andreas


Regards Andreas MCPD SharePoint 2010. Please remember to mark your question as "answered"/"Vote helpful" if this solves/helps your problem.

Change Sheet tab color of excel file using Open XML

$
0
0

Hi,

I want to change the sheet tab color of an excel Xlsx  document. I am using the following code but it does not set the sheet color. I get object reference exception when I set the sheet tab color.

publicstaticstring filepath =@"C:\Test\Book1.xlsx";privatestaticvoidChangeSheetcolor(){try{using(SpreadsheetDocument spreadSheetDocument =SpreadsheetDocument.Open(filepath,false)){WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();//my codeWorksheetPart worksheetPart =GetWorksheetPartByName(spreadSheetDocument,"Sheet1");if(worksheetPart !=null){//   worksheetPart.Worksheet.SheetProperties.TabColor.Rgb = DocumentFormat.OpenXml.HexBinaryValue.FromString("Red");
                        worksheetPart.Worksheet.SheetProperties.TabColor.Rgb=DocumentFormat.OpenXml.HexBinaryValue.FromString("#CCCCCC");// Save the worksheet.
                        worksheetPart.Worksheet.Save();}}}catch(Exception ex){}}privatestaticWorksheetPartGetWorksheetPartByName(SpreadsheetDocument document,string sheetName){IEnumerable<Sheet> sheets =
               document.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>().Where(s => s.Name== sheetName);if(sheets.Count()==0){//does not existreturnnull;}string relationshipId = sheets.First().Id.Value;WorksheetPart worksheetPart =(WorksheetPart)
                 document.WorkbookPart.GetPartById(relationshipId);return worksheetPart;}

How to change the sheet tab color using Open XML dlls.

Thanks

Ashok

MemoryStream and WordprocessingDocument

$
0
0

Hi Everyone, 

 I have a problem when using the WordProcessingDocument object together with a MemoryStream object. 

 My code is the following. 

MemoryStream stream = new MemoryStream(loanDocumentViewModel.DocumentContent);

            //using (MemoryStream stream = new MemoryStream(data)) //;MemoryStream ms = new MemoryStream(dc.DocumentContent))
            //{
            using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
            //using (WordprocessingDocument doc = WordprocessingDocument.Open(@"Documents\OtherDocuments\copy.docx", true))
            {

              DocumentSettingsPart docSett = doc.MainDocumentPart.DocumentSettingsPart;
                docSett.RootElement.Append(new DocumentProtection { Edit = DocumentProtectionValues.ReadOnly });
                docSett.RootElement.Save();

                doc.MainDocumentPart.Document.Save();
            }

The dc.DocumentContent is a Array readed from a Database. 

When I save my object into the Database again and open it. 

   Word is telling me that the file is corrupt, but It can be opened. 

Any clues on what wrong with the code?

I have tried to do the same operation, with a plain file and that works perfectly. 

Best Regards

  Lars 

Adding image to word document header

$
0
0

I am trying to add image to word document in the header.

The image gets added but it is coming as cross icon saying 'this image currently can not be displayed'

 using (MemoryStream stream = new MemoryStream(sourceDoc.FilePayload))
                    {



                        stream.Seek(0, SeekOrigin.Begin);

                        imagePart.FeedData(stream);

                    }

Can not share much code at this point of time, but any example around adding image inside the header will be usefull. In the header i have container with fix name where I am adding the image.

Viewing all 1288 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>