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