Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a barchart to a OpenXML created document

Tags:

openxml

My C# app uses OpenXML to create a MSWord doc with several tables in it already. The last part is to add a barchart. I can't find a good example of this case.

Thanks for your help!

I am creating the document from scratch. Starting with:

using (WordprocessingDocument myDoc = WordprocessingDocument.Create(documentStream, WordprocessingDocumentType.Document, autoSave: true))

Then I add new tables and paragraphs in C# code. All that is working until I get to the barchart. I found a sample project that inserts a piechart into a word document but I don't understand the differences between the chart types to convert it. Here is the piechart sample project that I found:

https://code.msdn.microsoft.com/office/How-to-create-Chart-into-a7d424f6

Thanks for your help!

like image 884
HenryM Avatar asked Feb 22 '17 21:02

HenryM


People also ask

How do you add references to open DocumentFormat OpenXml?

Go to your Solution Explorer > right click on references and then click Manage NuGet Packages . Then search in tab "Online" for DocumentFormat. OpenXml and install it. After you can use DocumentFormat.

How do I make text bold in OpenXml?

Bold fbld = new Bold();


2 Answers

To insert a basic bar chart, I would not look at the Pie Chart code and try to guess how to convert that to a Bar Chart.

A faster way to your solution is use the Open XML Productivity Tool. It has a feature that allows you to open 2 files, determine the difference between the two Open XML structures and will generate the code you need to make the first file look like the second file.

try this approach:

  1. Install the Open XML Productivity Tool
  2. Save your Word document (a clean version before Pie Chart piece was added) and name it NoBarChart.docx
  3. Make a copy of NoBarChart.docx name it WithBarChart.docx
  4. Open WithBarChart.docx with Word and add a Bar Chart (Insert->Chart->Bar).
  5. Style the Bar Chart with colors, formats, etc to meet your ultimate solution and save and close.
  6. Run the Open XML Productivity Tool and click the Compare Files button at the top.
  7. Choose NoBarChart.docx for source and WithBarChart.docx for target
  8. Click the highlighted parts of the file that are different and click the View Part Diff to see the differences in XML. Then click View Package Code and the tool will generate code to make the source look like the target.

Inspect the code it generates for ideas on how to add a Bar Chart. If some of the code is missing, you can generate the entire Target file with the tool.

A link to a simple WPF app that generates a blank doc with Bar chart is on GitHub. Here is a picture of the document:

enter image description here

This same approach can be used to generate most Word, Excel or PowerPoint files and features they provide.

like image 72
Taterhead Avatar answered Oct 05 '22 05:10

Taterhead


I followed the tutorial you followed that creates a Piechart. Then I managed to change that in order to insert a bar chart to the word document. I hope the following code will help you. I'm creating a data sample in the CreateBarChart function in order to create a column in the Barchart.

public static WordprocessingDocument CreateBarChart(WordprocessingDocument document)//List<ChartSubArea> chartList,
    {
        string title = "New Chart";

        Dictionary<string, int> data = new Dictionary<string, int>();
        data.Add("abc", 1);

        // Get MainDocumentPart of Document
        MainDocumentPart mainPart = document.AddMainDocumentPart();
        mainPart.Document = new Document(new Body());

        // Create ChartPart object in Word Document
        ChartPart chartPart = mainPart.AddNewPart<ChartPart>("rId110");

        // the root element of chartPart 
        dc.ChartSpace chartSpace = new dc.ChartSpace();
        chartSpace.Append(new dc.EditingLanguage() { Val = "en-us" });

        // Create Chart 
        dc.Chart chart = new dc.Chart();
        chart.Append(new dc.AutoTitleDeleted() { Val = true });

        // Define the 3D view
        dc.View3D view3D = new dc.View3D();
        view3D.Append(new dc.RotateX() { Val = 30 });
        view3D.Append(new dc.RotateY() { Val = 0 });

        // Intiliazes a new instance of the PlotArea class
        dc.PlotArea plotArea = new dc.PlotArea();
        BarChart barChart = plotArea.AppendChild<BarChart>(new BarChart(new BarDirection()
        { Val = new EnumValue<BarDirectionValues>(BarDirectionValues.Column) },
           new BarGrouping() { Val = new EnumValue<BarGroupingValues>(BarGroupingValues.Clustered) }));

        plotArea.Append(new dc.Layout());


        dc.ChartShapeProperties chartShapePros = new dc.ChartShapeProperties();

        uint i = 0;
        // Iterate through each key in the Dictionary collection and add the key to the chart Series
        // and add the corresponding value to the chart Values.
        foreach (string key in data.Keys)
        {
            BarChartSeries barChartSeries = barChart.AppendChild<BarChartSeries>(new BarChartSeries(new Index()
            {
                Val =
                new UInt32Value(i)
            },
                new Order() { Val = new UInt32Value(i) },
                new SeriesText(new NumericValue() { Text = key })));

            StringLiteral strLit = barChartSeries.AppendChild<CategoryAxisData>(new CategoryAxisData()).AppendChild<StringLiteral>(new StringLiteral());
            strLit.Append(new PointCount() { Val = new UInt32Value(1U) });
            strLit.AppendChild<StringPoint>(new StringPoint() { Index = new UInt32Value(0U) }).Append(new NumericValue(title));

            NumberLiteral numLit = barChartSeries.AppendChild<DocumentFormat.OpenXml.Drawing.Charts.Values>(
                new DocumentFormat.OpenXml.Drawing.Charts.Values()).AppendChild<NumberLiteral>(new NumberLiteral());
            numLit.Append(new FormatCode("General"));
            numLit.Append(new PointCount() { Val = new UInt32Value(1U) });
            numLit.AppendChild<NumericPoint>(new NumericPoint() { Index = new UInt32Value(0u) }).Append
            (new NumericValue(data[key].ToString()));

            i++;
        }

        barChart.Append(new AxisId() { Val = new UInt32Value(48650112u) });
        barChart.Append(new AxisId() { Val = new UInt32Value(48672768u) });

        // Add the Category Axis.
        CategoryAxis catAx = plotArea.AppendChild<CategoryAxis>(new CategoryAxis(new AxisId()
        { Val = new UInt32Value(48650112u) }, new Scaling(new Orientation()
        {
            Val = new EnumValue<DocumentFormat.
            OpenXml.Drawing.Charts.OrientationValues>(DocumentFormat.OpenXml.Drawing.Charts.OrientationValues.MinMax)
        }),
           new AxisPosition() { Val = new EnumValue<AxisPositionValues>(AxisPositionValues.Bottom) },
           new TickLabelPosition() { Val = new EnumValue<TickLabelPositionValues>(TickLabelPositionValues.NextTo) },
           new CrossingAxis() { Val = new UInt32Value(48672768U) },
           new Crosses() { Val = new EnumValue<CrossesValues>(CrossesValues.AutoZero) },
           new AutoLabeled() { Val = new BooleanValue(true) },
           new LabelAlignment() { Val = new EnumValue<LabelAlignmentValues>(LabelAlignmentValues.Center) },
           new LabelOffset() { Val = new UInt16Value((ushort)100) }));

        // Add the Value Axis.
        ValueAxis valAx = plotArea.AppendChild<ValueAxis>(new ValueAxis(new AxisId() { Val = new UInt32Value(48672768u) },
        new Scaling(new Orientation()
        {
            Val = new EnumValue<DocumentFormat.OpenXml.Drawing.Charts.OrientationValues>(
            DocumentFormat.OpenXml.Drawing.Charts.OrientationValues.MinMax)
        }),
        new AxisPosition() { Val = new EnumValue<AxisPositionValues>(AxisPositionValues.Left) },
        new MajorGridlines(),
        new DocumentFormat.OpenXml.Drawing.Charts.NumberingFormat()
        {
            FormatCode = new StringValue("General"),
            SourceLinked = new BooleanValue(true)
        }, new TickLabelPosition()
        {
            Val = new EnumValue<TickLabelPositionValues>
            (TickLabelPositionValues.NextTo)
        }, new CrossingAxis() { Val = new UInt32Value(48650112U) },
        new Crosses() { Val = new EnumValue<CrossesValues>(CrossesValues.AutoZero) },
        new CrossBetween() { Val = new EnumValue<CrossBetweenValues>(CrossBetweenValues.Between) }));

        // create child elements of the c:legend element
        dc.Legend legend = new dc.Legend();
        legend.Append(new dc.LegendPosition() { Val = LegendPositionValues.Right });
        dc.Overlay overlay = new dc.Overlay() { Val = false };
        legend.Append(overlay);

        dc.TextProperties textPros = new DocumentFormat.OpenXml.Drawing.Charts.TextProperties();
        textPros.Append(new d.BodyProperties());
        textPros.Append(new d.ListStyle());

        d.Paragraph paragraph = new d.Paragraph();
        d.ParagraphProperties paraPros = new d.ParagraphProperties();
        d.DefaultParagraphProperties defaultParaPros = new d.DefaultParagraphProperties();
        defaultParaPros.Append(new d.LatinFont() { Typeface = "Arial", PitchFamily = 34, CharacterSet = 0 });
        defaultParaPros.Append(new d.ComplexScriptFont() { Typeface = "Arial", PitchFamily = 34, CharacterSet = 0 });
        paraPros.Append(defaultParaPros);
        paragraph.Append(paraPros);
        paragraph.Append(new d.EndParagraphRunProperties() { Language = "en-Us" });

        textPros.Append(paragraph);
        legend.Append(textPros);

        // Append c:view3D, c:plotArea and c:legend elements to the end of c:chart element
        chart.Append(view3D);
        chart.Append(plotArea);
        chart.Append(legend);

        // Append the c:chart element to the end of c:chartSpace element
        chartSpace.Append(chart);

        // Create c:spPr Elements and fill the child elements of it
        chartShapePros = new dc.ChartShapeProperties();
        d.Outline outline = new d.Outline();
        outline.Append(new d.NoFill());
        chartShapePros.Append(outline);

        // Append c:spPr element to the end of c:chartSpace element
        chartSpace.Append(chartShapePros);

        chartPart.ChartSpace = chartSpace;

        // Generate content of the MainDocumentPart
        GeneratePartContent(mainPart);

        return document;

    }
public static void GeneratePartContent(MainDocumentPart mainPart)
    {
        w.Paragraph paragraph = new w.Paragraph() { RsidParagraphAddition = "00C75AEB", RsidRunAdditionDefault = "000F3EFF" };

        // Create a new run that has an inline drawing object
        w.Run run = new w.Run();
        w.Drawing drawing = new w.Drawing();

        dw.Inline inline = new dw.Inline();
        inline.Append(new dw.Extent() { Cx = 5274310L, Cy = 3076575L });
        dw.DocProperties docPros = new dw.DocProperties() { Id = (UInt32Value)1U, Name = "Chart 1" };
        inline.Append(docPros);

        d.Graphic g = new d.Graphic();
        d.GraphicData graphicData = new d.GraphicData() { Uri = "http://schemas.openxmlformats.org/drawingml/2006/chart" };
        dc.ChartReference chartReference = new ChartReference() { Id = "rId110" };
        graphicData.Append(chartReference);
        g.Append(graphicData);
        inline.Append(g);
        drawing.Append(inline);
        run.Append(drawing);
        paragraph.Append(run);

        mainPart.Document.Body.Append(paragraph);
    }

This is the result I'm seeing . Hope this will help. enter image description here

like image 25
Sachintha Nayanajith Avatar answered Oct 05 '22 07:10

Sachintha Nayanajith