使用带有 c# 和 ASP.net 的 openXML 在 powerpoint 中创建动态 table

create dynamic table in powerpoint using openXML with c# and ASP.net

我使用了这些链接并获得了一个工作代码,我可以在其中使用模板报告(包含占位符)并使用从数据库中获取的数据生成新的 PPTX 报告。我还有 4 个占位符,我需要在其中填充 4 个不同的数据 table。目前我正在使用该模板创建新幻灯片并替换文本的占位符,但对于 tables 我无法弄清楚。我可以使用下面的代码生成 table 但不是在占位符的位置。 Table 始终出现在屏幕中央。

使用的链接:https://blogs.msdn.microsoft.com/brian_jones/2008/11/18/creating-a-presentation-report-based-on-data/

https://code.msdn.microsoft.com/office/How-to-add-a-table-with-03578dde

从某个按钮点击事件中调用它:

 using (PresentationDocument presentationDocument = PresentationDocument.Open(slideName, true))
            {
                //Get the first slide from presentation
                SlidePart intitalSlide = presentationDocument.PresentationPart.SlideParts.First();
                AddNewSlide(presentationDocument, intitalSlide, 1045);
            }

 private void AddNewSlide(PresentationDocument presentationDocument, SlidePart _slideTemplate, int projectID)
    {
        PresentationPart parent = presentationDocument.PresentationPart;

        System.Data.DataTable dt = GetValueForPPTReport(projectID);

        var newSlidePart = parent.AddNewPart<SlidePart>("newSlide1");

        //copy the contents of the template slide to the new slide and attach the appropriate layout
        newSlidePart.FeedData(_slideTemplate.GetStream(FileMode.Open));
        newSlidePart.AddPart(_slideTemplate.SlideLayoutPart, _slideTemplate.GetIdOfPart(_slideTemplate.SlideLayoutPart));

        //Alter the placeholder text in new slide
        SetPlaceholder(newSlidePart, "txtProjectIDName", dt.Rows[0]["projName"].ToString());
        SetPlaceholder(newSlidePart, "txtProjType", dt.Rows[0]["proj_type"].ToString());
        SetPlaceholder(newSlidePart, "txtProbSt", dt.Rows[0]["proj_problem_state"].ToString());
        SetPlaceholder(newSlidePart, "txtGoal", dt.Rows[0]["proj_goal_obj"].ToString());
        SetPlaceholder(newSlidePart, "txtInScope", dt.Rows[0]["proj_in_scope"].ToString());
        SetPlaceholder(newSlidePart, "txtOutOfScope", dt.Rows[0]["proj_out_scope"].ToString());
        SetPlaceholder(newSlidePart, "txtCustomer", dt.Rows[0]["proj_who_customer"].ToString());
        SetPlaceholder(newSlidePart, "txtCTQ", dt.Rows[0]["proj_critical_to_qlty"].ToString());
        SetPlaceholder(newSlidePart, "txtDefect", dt.Rows[0]["proj_what_defect"].ToString());
        SetPlaceholder(newSlidePart, "txtDate", System.DateTime.Now.ToString("MM/dd/yyyy HH:mm"));

        //Add Tables here
        //tblXBenefit
        System.Data.DataTable dtXb = GetValueForPPTReportBenefit(1045);
        string placeholder = "tblXBenefit";
        List<D.Text> textListExif1 = newSlidePart.Slide.Descendants<D.Text>().Where(t => t.Text.Equals(placeholder)).ToList();
        if (textListExif1.Count == 1)
        {

        }

        List<OpenXmlElement> elements = new List<OpenXmlElement>();
        elements.Add(new P.NonVisualGraphicFrameProperties
            (new P.NonVisualDrawingProperties() { Id = 1, Name = "xyz" }, new P.NonVisualGraphicFrameDrawingProperties(), new ApplicationNonVisualDrawingProperties()));

        // Declare and instantiate the graphic Frame of the new slide 
        P.GraphicFrame graphicFrame = newSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame());

        // Specify the required Frame properties of the graphicFrame 
        ApplicationNonVisualDrawingPropertiesExtension applicationNonVisualDrawingPropertiesExtension = new ApplicationNonVisualDrawingPropertiesExtension() { Uri = "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}" };
        P14.ModificationId modificationId1 = new P14.ModificationId() { Val = 3229994563U };
        modificationId1.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
        applicationNonVisualDrawingPropertiesExtension.Append(modificationId1);
        graphicFrame.NonVisualGraphicFrameProperties = new P.NonVisualGraphicFrameProperties
        (new D.NonVisualDrawingProperties() { Id = 5, Name = "table 1" },
        new D.NonVisualGraphicFrameDrawingProperties(new D.GraphicFrameLocks() { NoGrouping = true }),
        new ApplicationNonVisualDrawingProperties(new ApplicationNonVisualDrawingPropertiesExtensionList(applicationNonVisualDrawingPropertiesExtension)));


        graphicFrame.Transform = new Transform(new D.Offset() { X = 1650609L, Y = 4343400L }, new D.Extents() { Cx = 6096000L, Cy = 741680L });

        // Specify the Griaphic of the graphic Frame 
        graphicFrame.Graphic = new D.Graphic(new D.GraphicData(GenerateTable()) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/table" });

        //save the changes to the slide
        newSlidePart.Slide.Save();

        //need to assign an id to the new slide and add it to the slideIdList
        //first figure out the largest existing id
        DocumentFormat.OpenXml.Presentation.SlideIdList slideIdList = parent.Presentation.SlideIdList;
        uint maxSlideId = 1;

        foreach (DocumentFormat.OpenXml.Presentation.SlideId slideId in slideIdList.ChildElements)
        {
            if (slideId.Id > maxSlideId) maxSlideId = slideId.Id;
        }

        //assign an id and add the new slide at the end of the list
        DocumentFormat.OpenXml.Presentation.SlideId newSlideId = new DocumentFormat.OpenXml.Presentation.SlideId { Id = ++maxSlideId, RelationshipId = parent.GetIdOfPart(newSlidePart) };
        slideIdList.Append(newSlideId);

        //Delete first template slide 
        SlideId tempSlideId = slideIdList.ChildElements[0] as SlideId;
        slideIdList.RemoveChild(tempSlideId);
    }
    private void SetPlaceholder(SlidePart slidePart, string placeholder, string value)
    {
        List<D.Text> textListExif1 = slidePart.Slide.Descendants<D.Text>().Where(t => t.Text.Equals(placeholder)).ToList();
        foreach (D.Text text in textListExif1)
        {
            text.Text = value;
        }
    }

    #region tables


    /// <summary> 
    /// Generate Table as below order: 
    /// a:tbl(Table) ->a:tr(TableRow)->a:tc(TableCell) 
    /// We can return TableCell object with CreateTextCell method 
    /// and Append the TableCell object to TableRow  
    /// </summary> 
    /// <returns>Table Object</returns> 
    private static D.Table GenerateTable()
    {
        string[,] tableSources = new string[,] { { "name", "age" }, { "Tom", "25" } };

        // Declare and instantiate table  
        D.Table table = new D.Table();


        // Specify the required table properties for the table 
        D.TableProperties tableProperties = new D.TableProperties() { FirstRow = true, BandRow = true };
        D.TableStyleId tableStyleId = new D.TableStyleId();
        tableStyleId.Text = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";


        tableProperties.Append(tableStyleId);


        // Declare and instantiate tablegrid and colums 
        D.TableGrid tableGrid1 = new D.TableGrid();
        D.GridColumn gridColumn1 = new D.GridColumn() { Width = 3048000L };
        D.GridColumn gridColumn2 = new D.GridColumn() { Width = 3048000L };


        tableGrid1.Append(gridColumn1);
        tableGrid1.Append(gridColumn2);
        table.Append(tableProperties);
        table.Append(tableGrid1);
        for (int row = 0; row < tableSources.GetLength(0); row++)
        {
            // Instantiate the table row 
            D.TableRow tableRow = new D.TableRow() { Height = 370840L };
            for (int column = 0; column < tableSources.GetLength(1); column++)
            {
                tableRow.Append(CreateTextCell(tableSources.GetValue(row, column).ToString()));
            }


            table.Append(tableRow);
        }
        return table;
    }


    /// <summary> 
    /// Create table cell with the below order: 
    /// a:tc(TableCell)->a:txbody(TextBody)->a:p(Paragraph)->a:r(Run)->a:t(Text) 
    /// </summary> 
    /// <param name="text">Inserted Text in Cell</param> 
    /// <returns>Return TableCell object</returns> 
    private static D.TableCell CreateTextCell(string text)
    {
        if (string.IsNullOrEmpty(text))
        {
            text = string.Empty;
        }

        // Declare and instantiate the table cell  
        // Create table cell with the below order: 
        // a:tc(TableCell)->a:txbody(TextBody)->a:p(Paragraph)->a:r(Run)->a:t(Text) 
        D.TableCell tableCell = new D.TableCell();


        //  Declare and instantiate the text body 
        D.TextBody textBody = new D.TextBody();
        D.BodyProperties bodyProperties = new D.BodyProperties();
        D.ListStyle listStyle = new D.ListStyle();


        D.Paragraph paragraph = new D.Paragraph();
        D.Run run = new D.Run();
        D.RunProperties runProperties = new D.RunProperties() { Language = "en-US", Dirty = false };
        D.Text text2 = new D.Text();
        text2.Text = text;
        run.Append(runProperties);
        run.Append(text2);
        D.EndParagraphRunProperties endParagraphRunProperties = new D.EndParagraphRunProperties() { Language = "en-US", Dirty = false };


        paragraph.Append(run);
        paragraph.Append(endParagraphRunProperties);
        textBody.Append(bodyProperties);
        textBody.Append(listStyle);
        textBody.Append(paragraph);


        D.TableCellProperties tableCellProperties = new D.TableCellProperties();
        tableCell.Append(textBody);
        tableCell.Append(tableCellProperties);


        return tableCell;
    }


    #endregion

好的,我可以将 table 放在我想要的任何位置,方法是更改​​此中的值.. 对于 X 和 Y.. 不确定 Cx 和 Cy 值的作用。这样就可以了

graphicFrame.Transform = new Transform(new D.Offset() { X = 1650609L, Y = 4343400L }, new D.Extents() { Cx = 6096000L, Cy = 741680L });

但是现在新的问题是我无法减小字体和table行高。 我尝试更改此值但没有任何效果。知道了会post过来

 D.TableRow tableRow = new D.TableRow() { Height = 370840L };

我不得不在 createTextCell 方法中进行此更改:添加了 FontSize=800

 D.RunProperties runProperties = new D.RunProperties() { Language = "en-US", Dirty = false, FontSize=800 };