using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Office2010.Drawing; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Presentation; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Xml; using System.Xml.Linq; using System.Xml.Xsl; using TEAMModelOS.SDK.Helper.Common.JsonHelper; using ColorMap = DocumentFormat.OpenXml.Presentation.ColorMap; using Theme = DocumentFormat.OpenXml.Drawing.Theme; namespace TEAMModelOS.Test.PPTX { public class PresentationConvert { const double inchpixel = 96.0, inchpt = 72.0, pxBase = 914400.0, rotBase = 60000; /// /// 处理一页PPT的元素 /// /// /// /// /// public object GetSlideElement(SlidePart slidePart, Theme theme, ColorMap colorMap) { List elements = new List(); var shapeTrees = from shap in slidePart.Slide.Descendants() select shap; if (shapeTrees.Count() > 0 && shapeTrees.First().ChildElements.Count > 0) { OpenXmlElementList openXmlElements = shapeTrees.First().ChildElements; int index = 0; foreach (OpenXmlElement element in openXmlElements) { PPTElement pptElement = null; if (element is DocumentFormat.OpenXml.Presentation.Shape shape) { pptElement = ShapeConvert(shape, theme, colorMap); } if (element is DocumentFormat.OpenXml.Presentation.Picture picture) { pptElement = PictureConvert(picture, slidePart); } if (element is DocumentFormat.OpenXml.AlternateContent content) { pptElement = AlternateContentConvert(content, theme, colorMap); } if (element is DocumentFormat.OpenXml.Presentation.GraphicFrame graphicFrame) { pptElement = GraphicFrameConvert(graphicFrame, theme, colorMap); } index++; elements.Add(pptElement); } } return elements; } public PPTElement GraphicFrameConvert(GraphicFrame graphicFrame, Theme theme, ColorMap colorMap) { DocumentFormat.OpenXml.Drawing.GraphicData graphicData = graphicFrame.ChildElements.First(); if (graphicData != null) { OpenXmlElement element = graphicData.ChildElements.First(); if (element != null) { if (element is DocumentFormat.OpenXml.Drawing.Table table) { return TableConvert(graphicFrame, theme, colorMap); } } } return null; } public PPTElement TableConvert(GraphicFrame graphicFrame, Theme theme, ColorMap colorMap) { return null; } /// /// 处理普通形状的元素 /// /// /// public PPTElement ShapeConvert(Shape shape ,Theme theme ,ColorMap colorMap) { // shape.base //文字颜色 string textColor = ""; //填充颜色 string fillColor = ""; // 形状类型 string type = "text"; //字体大小 int fontSize = 1800; //是否闭合形状 bool complete = false; ShapeProperties properties = shape.ShapeProperties; IEnumerable presetGeometries= GetPresetGeometry(properties); if (presetGeometries.Count() > 0) { type = presetGeometries.FirstOrDefault().Preset; } DocumentFormat.OpenXml.Drawing.Transform2D transform2D= GetTransform2D(properties); PPTElement element = new PPTElement() { type = type ,fontSize=fontSize}; if (transform2D != null) { element.complete = complete; element.offx = properties.Transform2D.Offset.X; element.offy = properties.Transform2D.Offset.Y; element.extx = properties.Transform2D.Extents.Cx; element.exty = properties.Transform2D.Extents.Cy; element.flipH = properties.Transform2D.HorizontalFlip != null ? BooleanValue.ToBoolean(properties.Transform2D.HorizontalFlip) : false; element.flipV = properties.Transform2D.VerticalFlip != null ? BooleanValue.ToBoolean(properties.Transform2D.VerticalFlip) : false; element.rot = properties.Transform2D.Rotation != null ? properties.Transform2D.Rotation.Value : 0; } ///获取runs的文本及颜色信息 var runs = from shap in shape.Descendants() select shap; foreach (var run in runs) { var runprps = from shap in run.Descendants() select shap; DocumentFormat.OpenXml.Drawing.RunProperties runProperties = runprps.FirstOrDefault(); if (runProperties != null && fontSize == 1800) { fontSize = runProperties.FontSize!=null && runProperties.FontSize>0 ?runProperties.FontSize.Value: fontSize; } var schemeColor = from shap in run.Descendants() select shap; var rgbColors = from shap in run.Descendants() select shap; textColor = GetSchemeColor(schemeColor ,theme ,colorMap); if (string.IsNullOrEmpty(textColor)) { textColor = GetRgbColor(rgbColors); } element.text = element.text + run.Text.InnerText; } if (string.IsNullOrEmpty(textColor)) { textColor = GetShapeStyleColor(shape.ShapeStyle, "Font", theme); } if (string.IsNullOrEmpty(fillColor)) { fillColor = GetShapeStyleColor(shape.ShapeStyle, "Fill", theme); } if (string.IsNullOrEmpty(fillColor)) { fillColor = GetPropertieFillColor(properties, theme, colorMap); } element.textColor = textColor; element.fillColor = fillColor; var custGeometrys = from shap in properties.Descendants() select shap; if (custGeometrys.Count() > 0) { var pathLists = from shap in custGeometrys.First().Descendants() select shap; if (pathLists.Count() > 0) { var moveTos = pathLists.First().ChildElements.OfType(); var lineTos = pathLists.First().ChildElements.OfType(); var BezierTos = pathLists.First().ChildElements.OfType(); } } return element; } /// /// 处理图片的元素 /// /// /// public PPTElement PictureConvert(Picture picture , SlidePart slidePart) { BlipFill blipFill = picture.BlipFill; var imageRid = blipFill.Blip.Embed.Value; string type = "picture"; IdPartPair idParie = slidePart.Parts.Where(x => x.RelationshipId == imageRid).FirstOrDefault(); ImagePart imagePart = (ImagePart)idParie.OpenXmlPart; var contentType = imagePart.ContentType; string base64 = ""; using (var stream = imagePart.GetStream()) { byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); stream.Close(); base64 = System.Convert.ToBase64String(buffer); base64 = "data:" + contentType + ";base64," + base64; } ShapeProperties properties = picture.ShapeProperties; PPTElement element = new PPTElement() { type = type }; if (properties != null && properties.Transform2D != null) { element.offx = properties.Transform2D.Offset.X; element.offy = properties.Transform2D.Offset.Y; element.extx = properties.Transform2D.Extents.Cx; element.exty = properties.Transform2D.Extents.Cy; element.flipH = properties.Transform2D.HorizontalFlip != null ? BooleanValue.ToBoolean(properties.Transform2D.HorizontalFlip) : false; element.flipV = properties.Transform2D.VerticalFlip != null ? BooleanValue.ToBoolean(properties.Transform2D.VerticalFlip) : false; element.rot = properties.Transform2D.Rotation != null ? properties.Transform2D.Rotation.Value : 0; } element.text = base64; return element; } /// /// 处理兼容元素 /// /// /// public PPTElement AlternateContentConvert(AlternateContent content, Theme theme, ColorMap colorMap) { AlternateContentChoice choice= content.ChildElements.First(); OpenXmlElement element = choice.ChildElements.First(); if (element != null) { if (element is DocumentFormat.OpenXml.Presentation.Shape shape) { var textMaths = from shap in shape.Descendants() select shap; if (textMaths.Count() > 0) { return MathConvert(shape ,theme ,colorMap); } } } return null; } /// /// 处理公式 /// /// /// /// /// public PPTElement MathConvert(DocumentFormat.OpenXml.Presentation.Shape shape, Theme theme, ColorMap colorMap) { //文字颜色 string textColor = ""; //填充颜色 string fillColor = ""; // 形状类型 string type = "math"; //字体大小 int fontSize = 1800; //是否闭合形状 bool complete = true; ShapeProperties properties = shape.ShapeProperties; //IEnumerable presetGeometries = GetPresetGeometry(properties); //if (presetGeometries.Count() > 0) //{ // type = presetGeometries.FirstOrDefault().Preset; //} DocumentFormat.OpenXml.Drawing.Transform2D transform2D = GetTransform2D(properties); PPTElement element = new PPTElement() { type = type, fontSize = fontSize }; if (transform2D != null) { element.complete = complete; element.offx = properties.Transform2D.Offset.X; element.offy = properties.Transform2D.Offset.Y; element.extx = properties.Transform2D.Extents.Cx; element.exty = properties.Transform2D.Extents.Cy; element.flipH = properties.Transform2D.HorizontalFlip != null ? BooleanValue.ToBoolean(properties.Transform2D.HorizontalFlip) : false; element.flipV = properties.Transform2D.VerticalFlip != null ? BooleanValue.ToBoolean(properties.Transform2D.VerticalFlip) : false; element.rot = properties.Transform2D.Rotation != null ? properties.Transform2D.Rotation.Value : 0; } //获取行内样式 if (string.IsNullOrEmpty(textColor)) { var rgbColor = from shap in shape.TextBody.Descendants() select shap; textColor =GetRgbColor(rgbColor); if (string.IsNullOrEmpty(textColor)) { var schemes = from shap in shape.TextBody.Descendants() select shap; textColor = GetSchemeColor(schemes ,theme ,colorMap); } } if (string.IsNullOrEmpty(textColor)) { textColor = GetShapeStyleColor(shape.ShapeStyle, "Font", theme); } if (string.IsNullOrEmpty(fillColor)) { fillColor = GetShapeStyleColor(shape.ShapeStyle, "Fill", theme); } if (string.IsNullOrEmpty(fillColor)) { fillColor = GetPropertieFillColor(properties, theme, colorMap); } element.fillColor = fillColor; element.textColor = textColor; var textMaths = from shap in shape.Descendants() select shap; var math= textMaths.First(); string elementData = ProcessOMath(math.InnerXml); element.text = elementData; return element; } /// /// 处理元素的Transform2D属性 /// /// /// public DocumentFormat.OpenXml.Drawing.Transform2D GetTransform2D(ShapeProperties properties) { if (properties != null) { return properties.Transform2D; } return null; } /// /// 处理元素的Transform2D属性 /// /// /// public IEnumerable GetPresetGeometry(ShapeProperties properties) { if (properties != null) { var presetGeometrys = from shap in properties.Descendants() select shap; return presetGeometrys; } return null; } /// /// 处理元素属性的填充色 /// /// /// public string GetPropertieFillColor(ShapeProperties properties, Theme theme, ColorMap colorMap) { string fillColor = ""; if (properties != null) { var solidFills = from shape in properties.Descendants() select shape; if ( solidFills.Count() > 0) { var propRgbColor = from shape in solidFills.First().Descendants() select shape; fillColor = GetRgbColor(propRgbColor); if (string.IsNullOrEmpty(fillColor)) { var colorScheme = from shape in solidFills.First().Descendants() select shape; fillColor = GetSchemeColor(colorScheme, theme, colorMap); } } } return fillColor; } /// /// 获取ShapeStyle样式表 各种属性 的颜色 /// /// /// /// /// public string GetShapeStyleColor(DocumentFormat.OpenXml.Presentation.ShapeStyle shapeStyle, string colorType, Theme theme) { if (shapeStyle == null) { return ""; } // 效果颜色 if (colorType.Equals("Effect")) { DocumentFormat.OpenXml.Drawing.SchemeColor EffectcolorScheme = shapeStyle.EffectReference.ChildElements.First(); return ColorForThemeClr(EffectcolorScheme.Val, theme); } // 线条颜色 if (colorType.Equals("Line")) { DocumentFormat.OpenXml.Drawing.SchemeColor LinecolorScheme = shapeStyle.LineReference.ChildElements.First(); return ColorForThemeClr(LinecolorScheme.Val, theme); } // 填充色 if (colorType.Equals("Fill")) { DocumentFormat.OpenXml.Drawing.SchemeColor FillcolorScheme = shapeStyle.FillReference.ChildElements.First(); return ColorForThemeClr(FillcolorScheme.Val, theme); } // 字体颜色 if (colorType.Equals("Font")) { DocumentFormat.OpenXml.Drawing.SchemeColor FontcolorScheme = shapeStyle.FontReference.ChildElements.First(); return ColorForThemeClr(FontcolorScheme.Val, theme); } return ""; } /// /// 获取声明式颜色 /// /// /// public string GetSchemeColor(IEnumerable colorScheme, Theme theme, ColorMap colorMap) { string rgbColor = ""; if (colorScheme.Count() > 0) { rgbColor = ColorForThemeClr(SchemeColorForColorMap(colorScheme.FirstOrDefault().Val.Value, colorMap), theme); } return rgbColor; } /// /// 获取RGBColor /// /// /// public string GetRgbColor(IEnumerable rgbColors) { string rgbColor = ""; if ( rgbColors.Count() > 0) { rgbColor = rgbColors.FirstOrDefault().Val; } return rgbColor; } /// /// 加载PPTX文件 /// /// /// public object LoadPresentation(string presentationFile) { using (PresentationDocument presentationDocument =PresentationDocument.Open(presentationFile, false)) { if (presentationDocument == null) { throw new ArgumentNullException("presentationDocument"); } // Get a PresentationPart object from the PresentationDocument object. PresentationPart presentationPart = presentationDocument.PresentationPart; if (presentationPart != null && presentationPart.Presentation != null) { var slideMasterParts = presentationPart.SlideMasterParts; ColorMap colorMap = null; Theme theme = null; foreach (var slideMasterPart in slideMasterParts) { if (colorMap != null && theme != null) { break; } colorMap = slideMasterPart.SlideMaster.ColorMap; theme = slideMasterPart.ThemePart.Theme; } // Get a Presentation object from the PresentationPart object. Presentation presentation = presentationPart.Presentation; if (presentation.SlideIdList != null) { //获取PPT 一页大小 int x = presentation.SlideSize.Cx; int y = presentation.SlideSize.Cy; // Get the title of each slide in the slide order. // 获取的是几页PPT数量 foreach (var slideId in presentation.SlideIdList.Elements()) { // 获取这一页 PPT 的id string id = slideId.RelationshipId; SlidePart slidePart = presentationPart.GetPartById(slideId.RelationshipId) as SlidePart; //获取当前页 PPT 的所有元素 GetSlideElement(slidePart, theme, colorMap); } } } return null; } } /// /// 在主题Theme中获取颜色 /// /// /// /// public static string ColorForThemeClr(string scv, Theme theme) { DocumentFormat.OpenXml.Drawing.ColorScheme colorScheme = theme.ThemeElements.ColorScheme; string colorStr = ""; if (scv.Equals("dk1")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Dark1Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Dark1Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } if (scv.Equals("dk2")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Dark2Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Dark2Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("accent1")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Accent1Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Accent1Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("accent2")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Accent2Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Accent2Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("accent3")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Accent3Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Accent3Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("accent4")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Accent4Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Accent4Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("accent5")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Accent5Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Accent5Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("accent6")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Accent6Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Accent6Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("lt1")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Light1Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Light1Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("lt2")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Light2Color.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Light2Color.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("hlink")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.Hyperlink.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.Hyperlink.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } else if (scv.Equals("folHlink")) { DocumentFormat.OpenXml.Drawing.SystemColor sysColor = colorScheme.FollowedHyperlinkColor.ChildElements.First(); if (sysColor != null) { return sysColor.LastColor; } DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColor = colorScheme.FollowedHyperlinkColor.ChildElements.First(); if (rgbColor != null) { return rgbColor.Val; } return colorStr; } return ""; } /// /// 按照ColorMap 去寻找对应的颜色 /// /// /// /// public static string SchemeColorForColorMap(DocumentFormat.OpenXml.Drawing.SchemeColorValues schemeColorValues, ColorMap colorMap) { string scv = schemeColorValues.ToString(); if (scv.Equals("Text1")) { return colorMap.Text1.ToString(); } if (scv.Equals("Text2")) { return colorMap.Text2.ToString(); } else if (scv.Equals("Accent1")) { return colorMap.Accent1.ToString(); } else if (scv.Equals("Accent2")) { return colorMap.Accent2.ToString(); } else if (scv.Equals("Accent3")) { return colorMap.Accent3.ToString(); } else if (scv.Equals("Accent4")) { return colorMap.Accent4.ToString(); } else if (scv.Equals("Accent5")) { return colorMap.Accent5.ToString(); } else if (scv.Equals("Accent6")) { return colorMap.Accent6.ToString(); } else if (scv.Equals("Background1")) { return colorMap.Background1.ToString(); } else if (scv.Equals("Background2")) { return colorMap.Background2.ToString(); } else if (scv.Equals("Hyperlink")) { return colorMap.Hyperlink.ToString(); } else if (scv.Equals("FollowedHyperlink")) { return colorMap.FollowedHyperlink.ToString(); } else if (scv.Equals("PhColor")) { return "PhColor"; } else if (scv.Equals("Dark1")) { return "dk1"; } else if (scv.Equals("Dark2")) { return "dk2"; } else if (scv.Equals("Light1")) { return "lt1"; } else if (scv.Equals("Light2")) { return "lt2"; } return null; } /// /// 转换Surrogate 类型的编码的字符串 /// /// /// public static Dictionary StringEncode(string xml) { Dictionary codeValues = new Dictionary(); Char[] charstr = xml.ToCharArray(); int len = charstr.Length; for (int i = 0; i < len; i++) { var stringBuilder = ""; string str = Char.ToString(charstr[i]); if (Char.GetUnicodeCategory(charstr[i]) == UnicodeCategory.Surrogate) { string str1 = Char.ToString(charstr[i + 1]); str += str1; var bytes = Encoding.UTF32.GetBytes(str); for (var j = 0; j < bytes.Length; j += 2) { stringBuilder = bytes[j + 1].ToString("x").PadLeft(2, '0') + bytes[j].ToString("x").PadLeft(2, '0') + stringBuilder; } var id = Convert.ToInt64(stringBuilder, 16); i += 1; string code = id + ""; codeValues.TryAdd(str, code); } } return codeValues; } /// /// 根据OfficeML转换为MathML /// /// /// public static string ProcessOMath(string innerXml) { Dictionary codeValues = StringEncode(innerXml); if (codeValues != null) { foreach (string codeValue in codeValues.Keys) { innerXml = Regex.Replace(innerXml, codeValue, codeValues[codeValue]); } } XElement element = XElement.Load(new StringReader(innerXml)); List elements = element.Elements().ToList(); element = elements.Where(x => x.Name.LocalName.Equals("oMath")).FirstOrDefault(); XslCompiledTransform xslTransform = new XslCompiledTransform(); xslTransform.Load("E:/document/OMML2MML.XSL"); string mathXml = element.ToString(); string officeML = string.Empty; using (TextReader tr = new StringReader(mathXml)) { using (XmlReader reader = XmlReader.Create(tr)) { using (MemoryStream ms = new MemoryStream()) { XmlWriterSettings settings = xslTransform.OutputSettings.Clone(); settings.ConformanceLevel = ConformanceLevel.Fragment; settings.OmitXmlDeclaration = true; settings.Encoding = Encoding.Unicode; XmlWriter xw = XmlWriter.Create(ms, settings); xslTransform.Transform(reader, xw); ms.Seek(0, SeekOrigin.Begin); using (StreamReader sr = new StreamReader(ms, Encoding.UTF8)) { officeML = sr.ReadToEnd(); } } } } officeML = officeML.Replace("mml:", ""); if (codeValues != null) { foreach (string codeValue in codeValues.Keys) { officeML = Regex.Replace(officeML, codeValues[codeValue], codeValue); } } return officeML; } } }