å¨ OpenXML ç PPT çææ¬çåä½æ¯ä¸ä¸ªæ¯è¾å¤æçæ¦å¿µï¼å³ä½¿å¨ OpenXML SDK çè¾ å©ä¸ï¼ä¹éè¦èªå·±åå¾å¤çé»è¾ãéè¿ ECMA 376 ææ¡£éé¢æ£è½å¨åå°çæè¿°ï¼å dotnetCampus.OfficeDocumentZipper å·¥å ·çå®éªå¸®å©ä¹ä¸ï¼ææ¸å°äºæ¬æå°è¦åè¯å¤§å®¶çè§åï¼ä»¥åé»è¾çå®ç°
æ大éç Office ç¸å ³è½¯ä»¶å¨è§£æ PPT æ档使ç¨çææ¬æ®µçåä½é½é常ç®åï¼å½ç¶ï¼è¿é¨åå¤çä¹å°±ä¸å ¨é¢
å 让å±çä¸ä¸ªç®åç PPT ææ¡£çåä½å®ä¹åæ³
<a:r>
<a:rPr lang="zh-CN" altLang="en-US" dirty="0" smtClean="0">
<a:ea typeface="楷ä½" panose="02010609060101010101" pitchFamily="49" charset="-122"/>
</a:rPr>
<a:t>ä¸è¡ææ¬</a:t>
</a:r>
请é®å½åææ¬çåä½æ¯ä»ä¹ï¼äººç±»ç®åå°±è½åçæ¯ â
â楷ä½â
â äº
é£ä¹æ´è¿ä¸æ¥çï¼å¦ä¸é¢ç PPT ææ¡£å¢ï¼
<a:r>
<a:rPr lang="zh-CN" altLang="en-US" sz="2000" dirty="0" smtClean="0">
<a:latin typeface="Jokerman" panose="02010609060101010101" pitchFamily="49" charset="-122"/>
<a:ea typeface="å®ä½" panose="02010609060101010101" pitchFamily="49" charset="-122"/>
</a:rPr>
<a:t>aææ¬</a:t>
</a:r>
æ¤æ¶ç â
âa:latinâ
ââ å â
âa:eaâ
â 表示çæ¯ä»ä¹ææï¼éè¦ä½¿ç¨åªä¸ªåä½æ对ï¼å ¶å®è¿æ¯ PPT çå 许西æåä¸æ使ç¨ä¸ååä½çåè½
â
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQDOxEzX3xCZlhXam9VbsUmepNXZy9CXwJWZ3xCdh1mcvZ2Lc1zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwIzX39GZhh2csATMflHLwEzX4xSZz91ZsAzMfRHLGZkRGZkRfJ3bs92YskmNhVTYykVNQJVMRhXVEF1X0hXZ0xiNx8VZ6l2cssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3IzNxEzM4gTMlVTY3U2YxYzX0UDNzETMxMzLcJTMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
â
è¿å°±æ¯éè¦è®©ä¸åçå符éæ©ä¸åçåä½çåè½ï¼è§£ææ¹å¼è¯·ç dotnet OpenXML ææ¬åä½çéæ©è§å
æ¯ä¸æ¯è§å¾æç¹å¤æäºï¼å ¶å®è¿è¿ä¸ç®å¤æç
ççä¸é¢è¿ä»½ç®æ´ç PPT ææ¡£
<p:txBody>
<a:bodyPr wrap="square" rtlCol="0">
<a:spAutoFit/>
</a:bodyPr>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="zh-CN" altLang="en-US" smtClean="0"/>
<a:t>ä¸è¡ææ¬</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
</p:txBody>
请é®è¿ä»½ææ¡£çåä½æ¯ä»ä¹ï¼å ¶å®ä¸é¢ç代ç 没æåä»»ä½çåä½ï¼é£ä¹ PPT æ¯å¦ä½ç¥éçï¼è¿å°±éè¦ç¨å°ä¸é¢ä»£ç ä¸ä¸ªæ²¡æåå®æçåè½ï¼å°±æ¯æ ·å¼å表äº
å°ä¼ä¼´å¯ä»¥æ³¨æå°ä¸é¢ä»£ç çä¸è¡å 容 â
â<a:lstStyle/>â
â è¿ä¸ªçæææ¯ä»ä¹ï¼å¨ OpenXML SDK éé¢æè¿ä¸ªå®ä¹ï¼è¯·ç代ç
var textBodyListStyle = textBody.ListStyle;
æåå¤äºè¿ä»½ç®æ´çææ¡£ï¼è¿ä»½ææ¡£å°éè¦ç¨å°æ¬æ说讲å°ç大é¨åç¥è¯æè½è§£æåºå®é çåä½æ¯åªä¸ªãæ¬æç¨çæµè¯ææ¡£æ¾å¨ githubâ 欢è¿å°ä¼ä¼´ä¸è½½æµè¯ãå¦å¤æ¨è dotnetCampus.OfficeDocumentZipper å·¥å ·ï¼è¿ä¸ªå·¥å ·å¯ä»¥æ´å¥½çåå©å°ä¼ä¼´æµè¯ææ¡£
æ´ä¸ªææ¬çå®ä¹å¦ä¸
<p:sp>
<p:nvSpPr>
<p:cNvPr id="4" name="ææ¬æ¡ 3"/>
<p:cNvSpPr txBox="1"/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="4168346" y="914401"/>
<a:ext cx="3048000" cy="369332"/>
</a:xfrm>
<a:prstGeom prst="rect"></a:prstGeom>
</p:spPr>
<p:txBody>
<a:bodyPr wrap="square" rtlCol="0"></a:bodyPr>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="zh-CN" altLang="en-US" smtClean="0"/>
<a:t>ä¸è¡ææ¬</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
</p:txBody>
</p:sp>
ä»ä¸é¢çå 容å¯ä»¥çå°ï¼è¿ä¸æ¯ä¸ä¸ªæ¾å¨å ä½ç¬¦çææ¬ï¼é£ä¹ä»ä¹æ¯æ¾å¨å ä½ç¬¦çææ¬ï¼å¦æ â
â<p:nvPr/>â
ââ 没æå 容ï¼é£ä¹å°±è¡¨ç¤ºä¸æ¯å ä½ç¬¦çææ¬ãèå¦ææ¯å ä½ç¬¦é£ä¹ â
âp:nvprâ
â å°ä¼æ¯å¦ä¸æ ¼å¼
<p:nvpr>
<p:ph type="ctrTitle">
</p:ph>
</p:nvpr>
å¯¹äº å ä½ç¬¦ éè¦éè¿ç»§æ¿å±æ§æ·»å æ´å¤å 容ï¼è¯·ç dotnet OpenXML SDK ææ¬å ä½ç¬¦è§£æ
å½ç¶ï¼æ¬æçä¾åä¸æ¯å ä½ç¬¦æ¯æ¯è¾ç®åçå ç´
ä½æ¯è¿ä¸ªå½¢ç¶æ²¡æç»ä¸ä¸ªæç¡®çåä½ï¼é£ä¹è¯·é®è¿ä¸ªå½¢ç¶ç¨çåä½æ¯ä»ä¹ï¼æ¤æ¶æ¶åå°äºä¸ä¸ªææ¬æ ·å¼ç级çæ¦å¿µ
å¨ææ¡£éé¢æè¿ä¸å¥ä»£ç â
â<a:lstStyle/>â
â 表示ææ¬æ¬èº«æ²¡æéæ°å®ä¹æ ·å¼ç级ï¼éè¦ä¸å±å±å¯»æ¾
å¯ä»¥å¨ Slide ç Layout å Slide ç Master æ¾å°å¯¹åºç â
âp:txStylesâ
ââ å 容ï¼ä¸è¿æ ·å¼ç级æ¯å¦å¤çç¥è¯ç¹ï¼ä¸å¨æ¬æå´å ãå¯ä»¥åè¯å¤§å®¶çæ¯å¨è¿ä»½æµè¯è¯¾ä»¶éé¢ï¼å ¶å® SlideLayout å SlideMaster ç â
âp:txStylesâ
ââ é½ä¸æ¯æ¤ææ¬çæ ·å¼ãå 为è¿ä¸ªå ç´ éè¦çæ¯ â
â<p:defaultTextStyle>â
â é»è®¤ææ¬æ ·å¼
é£ä¹å¨åªå¯ä»¥æ¿å° â
â<p:defaultTextStyle>â
â é»è®¤ææ¬æ ·å¼ï¼è¿æ¯ææ¡£å ¨å±ç设置ï¼å æ¤éè¦å¨ Presentation.xml æ¿å°ï¼å¯¹åºç OpenXML 代ç å¦ä¸
using (var presentationDocument =
DocumentFormat.OpenXml.Packaging.PresentationDocument.Open("æµè¯.pptx", false))
{
var presentationPart = presentationDocument.PresentationPart;
var presentation = presentationPart.Presentation;
var defaultTextStyle = presentation.DefaultTextStyle;
}
è¿å°±æ¯ DefaultTextStyle çè·åæ¹æ³ï¼ä» Presentation ç±»çå±æ§å®ä¹ä¹è½äºè§£å°è¿ä¸ªè§å
äºæ¯æç §è§åï¼é»è®¤å¦æææ¬åå¨ ListStyle é£ä¹å°±ä½¿ç¨ææ¬èªå·±çï¼å¦åéç¨æ档级çãå½ç¶ï¼å¦ææ¯å ä½ç¬¦çå ç´ ï¼é£å°±æ´å¤æäºï¼å±å 忽ç¥
å¨è¿ä»½è¯¾ä»¶éé¢ææ¬å ç´ æ²¡æèªå·±çæ ·å¼éåï¼å¯ä»¥éè¿ä¸é¢ä»£ç å¤æ
var defaultTextStyle = presentation.DefaultTextStyle;
var textBody = shape.TextBody;
var textBodyListStyle = textBody.ListStyle;
Debug.Assert(textBodyListStyle.ChildElements.Count == 0);
è TextStyle å ¶å®å确说æ¯ä¸ä¸ªå表ï¼æä» Level1 å° Level9 çæ ·å¼ï¼é£ä¹å¦ä½ç¥é使ç¨åªä¸ä¸ª
å ¶å®æ ·å¼å表é对çæ¯æ®µçº§çï¼ä¹å°±æ¯ä¸ä¸ªææ¬éé¢çå¤ä¸ªä¸åç段è½å¯ä»¥ä½¿ç¨ä¸åçæ ·å¼ç级ï¼å¯ä»¥ä½¿ç¨å¦ä¸ä»£ç
var paragraph = textBody.Descendants<Paragraph>().First();
var level = paragraph.ParagraphProperties?.Level?.Value ?? 1;
Debug.Assert(level == 1);
Debug.Assert(paragraph.ParagraphProperties == null);
var paragraphProperties = defaultTextStyle.Level1ParagraphProperties;
è¿æ¯æµè¯ä»£ç ï¼å æ¤ä» è·å第ä¸æ®µï¼èæç §æµè¯çææ¡£ï¼å¯ä»¥äºè§£å°æ¤æ¶ç level å°±æ¯ 1 åæ¶ææ¬æ¬èº«æ²¡æéåæ ·å¼ï¼å æ¤ä½¿ç¨çå°±æ¯ defaultTextStyle.Level1ParagraphProperties ä½ä¸ºæ®µè½æ ·å¼
ææ¬çæ ·å¼æ®µè½éé¢å å«äºæ®µè½çé»è®¤å±æ§ï¼ä¹å°±æ¯ææ¬ç Run å¦æ没æå®ä¹å¦åä½çè¿äºå±æ§ï¼å°ä¼ä½¿ç¨æ®µè½é»è®¤å±æ§
å¯ä»¥ä½¿ç¨ä¸é¢ä»£ç è·å段è½çææ¬
foreach (var run in paragraph.Descendants<Run>())
{
var runProperties = run.RunProperties;
var eastAsianFont = runProperties.GetFirstChild<EastAsianFont>();
Debug.Assert(eastAsianFont == null);
// 忽ç¥ä»£ç
}
ä»ä¸é¢ä»£ç å¯ä»¥çå°ï¼æµè¯ææ¡£æ¯ä¸åå¨ EastAsianFont åä½çï¼æ¤æ¶å°±éè¦ç¨å° defaultTextStyle å®ä¹çå 容ï¼å¨å¼å§å代ç ä¹åï¼å çä¸ä¸å¨ææ¡£éé¢æ¯å¦ä½å®ä¹ç
å¨æµè¯ææ¡£éé¢ç Presentation.xml æ¯è¿æ ·å®ä¹çï¼è¿ä»½ææ¡£æ¾å¨ ââgithubââ 欢è¿å°ä¼ä¼´è§£å缩
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:presentation xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" saveSubsetFonts="1">
<p:sldMasterIdLst>
<p:sldMasterId id="2147483648" r:id="rId1"/>
</p:sldMasterIdLst>
<p:sldIdLst>
<p:sldId id="256" r:id="rId2"/>
</p:sldIdLst>
<p:sldSz cx="12192000" cy="6858000"/>
<p:notesSz cx="6858000" cy="9144000"/>
<p:defaultTextStyle>
<a:defPPr>
<a:defRPr lang="en-US"/>
</a:defPPr>
<a:lvl1pPr marL="0" algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1">
<a:defRPr sz="1800" kern="1200">
<a:solidFill>
<a:schemeClr val="tx1"/>
</a:solidFill>
<a:latin typeface="+mn-lt"/>
<a:ea typeface="æå¾·ç"/>
<a:cs typeface="+mn-cs"/>
</a:defRPr>
</a:lvl1pPr>
</p:defaultTextStyle>
<p:extLst>
<p:ext uri="{EFAFB233-063F-42B5-8137-9DF3F51BA10A}">
<p15:sldGuideLst xmlns:p15="http://schemas.microsoft.com/office/powerpoint/2012/main"/>
</p:ext>
</p:extLst>
</p:presentation>
ä¹è®¸çèµ·æ¥çé»è¾æç¹å¤æï¼ä½æ¯å®é éè¦äºè§£çé»è¾å¦ä¸
<a:lvl1pPr marL="0" algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1">
<a:defRPr sz="1800" kern="1200">
<a:solidFill>
<a:schemeClr val="tx1"/>
</a:solidFill>
<a:latin typeface="+mn-lt"/>
<a:ea typeface="æå¾·ç"/>
<a:cs typeface="+mn-cs"/>
</a:defRPr>
</a:lvl1pPr>
æ¤æ¶ç paragraphProperties çæ°æ®ï¼å°æ¯ä¸é¢çå 容ï¼é»è®¤ä½¿ç¨ Level1 çå±æ§
var paragraphProperties = defaultTextStyle.Level1ParagraphProperties;
æ¤æ¶è·åçæ¹æ³å¦ä¸é¢ä»£ç
eastAsianFont = paragraphProperties.GetFirstChild<DefaultRunProperties>()
.GetFirstChild<EastAsianFont>();
var typeface = eastAsianFont.Typeface.Value;
Console.WriteLine($"åä½æ¯ {typeface}");
// typeface == "æå¾·ç"
å½ç¶ï¼å°ä¼ä¼´å¦æ没æå»é 读 dotnet OpenXML ææ¬åä½çéæ©è§å ä¹è®¸å°±ä¼å¥½å¥ä¸ºä»ä¹æè¿éç代ç åªè¯»å EastAsianFont åä½ï¼è忽ç¥å ¶ä»çåä½
â
â
ä»æ¬æå°å½ååªæ¯å¨åè¯å¤§å®¶å¦ä½æ¿å°å¯¹çåä½å±æ§ï¼åä½å±æ§æ¯å¯¹äºææ¬æ®µ Run æ¥è¯´çï¼èä¸æ¯æ®µè½æææ¬çãä½æ¯å¦æææ¬æ®µ Run ä¸åå¨åä½çå®ä¹ï¼é£ä¹æ¤æ¶éè¦å°è¯å»è·å段è½çé»è®¤å±æ§å®ä¹ãä½æ¯å¦æ段è½æ²¡æä»»ä½é»è®¤å±æ§å®ä¹ï¼å°±éè¦è·åææ¡£çææ¬æ ·å¼å®ä¹
è¿é¨åé»è¾å±äº PPT çé»è¾ï¼æå¨ ECMA 376 没ææ¾å°ç¸å ³çæè¿°ï¼ä¹å°±æ¯è¿é¨åé»è¾æ¯æ²¡æææ¡£å®ä¹çãè¿ä¹å°±æ¯ OpenXML SDK è¿ä¸ªåºæ²¡ææä¾è·åææ¬æç»å±æ§çæ¹æ³çåå
å¦æå°ä¼ä¼´è®¤ä¸ºè¿ä¹ç®åå°±è·åå°åä½äºï¼é£ä¹åçä½ ä½¿ç¨äºä¸ä¸ªå« â
â+mn-eaâ
â çåä½ãççï¼è¿æ¯ä¸ä¸ªä»ä¹åä½ï¼å ¶å®è¿æ¯ä¸ä¸ªæ趣çåæ³
å¨æ¾å°å¯¹åºçåä½å±æ§çæ¶åï¼ä¸ä¸å®æ¿å°æç»ä½¿ç¨çåä½ï¼å¦æå¤ææ¯ â
â+mn-eaâ
â çæ ¼å¼ï¼é£ä¹å°±éè¦åè¿ä¸æ¥ç转æ¢
é¦å å¤æçæ£å代ç å¦ä¸ï¼å¦æè¿ä¸ªä»£ç åéäºï¼è¿è¯·å°ä¼ä¼´åè¯æ
private static readonly Regex ThemeFontTypePattern =
new Regex(@"(^\+(mn|mj)\-(lt|cs|ea)$)", RegexOptions.Compiled);
è¿ä¸ªå®ä¹çæ¹å¼æ¯ FontScheme çå®ä¹ï¼éè¦å 解æè¿ä¸ªå符串æè½äºè§£
æç §å®ä¹ï¼éè¦å°è¿ä¸ªå符串å为两个é¨åï¼ä¸ä¸ªå°±æ¯ â
â+mnâ
ââ å¦ä¸ä¸ªå°±æ¯ â
â-eaâ
â 两个é¨å
åé¢é¨å表示å¦ä¸
- mnï¼MinorFont
- mjï¼MajorFont
åé¢çæ举表示å¦ä¸
public enum FontLang
{
/// <summary>
/// lt
/// </summary>
LatinFont,
/// <summary>
/// ea
/// </summary>
EastAsianFont,
/// <summary>
/// cs
/// </summary>
ComplexScriptFont,
/// <summary>
/// sym
/// </summary>
SymbolFont,
/// <summary>
/// ä¸ç¥éåªä¸ªè¯è¨
/// </summary>
Unknown,
}
é£ä¹ MinorFont å MajorFont æ¯ä»ä¹ææï¼å ¶å®å°±æ¯æ£æåæ é¢çæ示ï¼å°ä¼ä¼´å¯ä»¥å¨ PPT çåä½çå°ææ¬å·åçæ é¢åæ£æï¼å°±æ¯å¯¹åºçè¿ä¸¤ä¸ªå±æ§çå«ä¹
â
â
è¿ä¸ªä¸»é¢å¯ä»¥å¦ä½è·åï¼è¯·ç代ç
private static FontScheme GetFontScheme(SlidePart slidePart)
{
if (slidePart.ThemeOverridePart?.ThemeOverride?.FontScheme != null)
{
return slidePart.ThemeOverridePart.ThemeOverride.FontScheme;
}
var slideLayoutPart = slidePart.SlideLayoutPart;
//ä»SlideLayoutè·åtheme
if (slideLayoutPart.ThemeOverridePart?.ThemeOverride?.FontScheme != null)
{
return slideLayoutPart.ThemeOverridePart.ThemeOverride.FontScheme;
}
var slideMasterPart = slideLayoutPart.SlideMasterPart;
//ä»SlideMasterè·åtheme
return slideMasterPart?.ThemePart?.Theme?.ThemeElements?.FontScheme;
}
请å°ä¼ä¼´æ¢ä¸ä»½æµè¯è¯¾ä»¶ç¨æ¥æµè¯é»è¾ï¼æµè¯ç课件æ¾å¨ ââgithubââ è¿ä»½è¯¾ä»¶æ´æ¹äº Presentation.xml å®ä¹ä¸ºä¸é¢ä»£ç
<a:lvl1pPr marL="0" algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1">
<a:defRPr sz="1800" kern="1200">
<a:solidFill>
<a:schemeClr val="tx1"/>
</a:solidFill>
<a:latin typeface="+mn-lt"/>
<a:ea typeface="+mn-ea"/>
<a:cs typeface="+mn-cs"/>
</a:defRPr>
</a:lvl1pPr>
å¯ä»¥çå°çæ¯åæ¬æ¯æå ·ä½çåä½ç â
âa:eaâ
ââ 被æ´æ¹ä¸º â
âa:ea typeface="+mn-ea"â
â éè¦ä½¿ç¨ FontScheme æ¾å°å¯¹åºçé»è¾
å¨è¿ä»½æµè¯è¯¾ä»¶éé¢ï¼å ¶å®åªæ Theme1.xml æ件ææå®é çå®ä¹ï¼ä¹å°±æ¯ â
âslideMasterPart?.ThemePart?.Theme?.ThemeElements?.FontSchemeâ
â ææè¿åå¼
if (ThemeFontTypePattern.IsMatch(typeface))
{
// è¿å
¥è¿ä¸ªåæ¯ï¼åä½æ¯ +mn-ea åä½
// è¿ä¸ªåä½çææéé¢ mn 表示 Body åä½
// è mj 表示 Title åä½ï¼ä¹å°±æ¯ Major åä½
// åç»ç ea å lt ç表示éç¨ä¸äºæåææä¸æç
// æ¤æ¶éè¦è·ååä½ä¸»é¢
var fontScheme = GetFontScheme(slidePart);
FontCollectionType fontCollection;
// mn ç n ä¼ å
¥åç¬¦ä¸²æ¯ +mn-ea ä¹å°±æ¯ç¬¬ä¸ä¸ªå符
if (typeface[2] == 'n')
{
fontCollection = fontScheme.MinorFont;
}
else
{
fontCollection = fontScheme.MajorFont;
}
// 忽ç¥ä»£ç
}
æç §æ¬æçé»è¾ï¼ä¸ä¸æ¥éè¦è§£ææ¯å ·ä½çè¯è¨
FontLang fontLang = FontLang.Unknown;
if (typeface.Contains("lt"))
{
fontLang = FontLang.LatinFont;
}
else if (typeface.Contains("cs"))
{
fontLang = FontLang.ComplexScriptFont;
}
else if (typeface.Contains("ea"))
{
fontLang = FontLang.EastAsianFont;
}
å¨å¼å§è¯»ååä½ä¹åï¼å çä¸ä¸ Theme1.xml æ件çå®ä¹
<a:fontScheme name="Office">
<a:majorFont>
<a:latin typeface="Calibri Light" panose="020F0302020204030204"/>
<a:ea typeface=""/>
<a:cs typeface=""/>
<a:font script="Jpan" typeface="ï¼ï¼³ ï¼°ã´ã·ãã¯"/>
<a:font script="Hang" typeface="ë§ì ê³ ë"/>
<a:font script="Hans" typeface="å®ä½"/>
<a:font script="Hant" typeface="æ°ç´°æé«"/>
</a:majorFont>
<a:minorFont>
<a:latin typeface="Calibri" panose="020F0502020204030204"/>
<a:ea typeface=""/>
<a:cs typeface=""/>
<a:font script="Jpan" typeface="ï¼ï¼³ ï¼°ã´ã·ãã¯"/>
<a:font script="Hang" typeface="ë§ì ê³ ë"/>
<a:font script="Hans" typeface="éæ¯"/>
<a:font script="Hant" typeface="æ°ç´°æé«"/>
</a:minorFont>
</a:fontScheme>
å½ç¶ä¹è®¸ä½ ä¼åç°æ¤æ¶ç typeface ä¸æ¯æ个åä½æ "mn-lt" çï¼èæ¯ä¸ä¸ªç©ºå符串ãæ¤æ¶å°±éè¦ç¨å° Theme Font Languagesï¼ThemeFontLang ECMA-376 17.15.1.88ï¼çåè½äº
请é®æ¤æ¶çåä½æ¯ä»ä¹ï¼
â
â
为ä»ä¹æ¯è¯»å â
â<a:font script="Hans" typeface="éæ¯"/>â
â ä½ä¸ºåä½çï¼åå å°±æ¯éè¦å å¤æè¯è¨
å°ä¼ä¼´æ¯å¦è¿è®°å¾å¨ Run çå±æ§å®ä¹
<a:p>
<a:r>
<a:rPr lang="zh-CN" altLang="en-US" sz="2000" smtClean="0"/>
<a:t>ä¸è¡ææ¬</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
è¿éæä¸ä¸ªå±æ§ â
âlangâ
â æ¯ä»ä¹ä½ç¨ï¼å ¶å®å°±æ¯ç¨æ¥å³å®ä½¿ç¨é£ä¸ª Script 对åºçåä½ç
è zh-CN å Hans æä»ä¹å ³ç³»ï¼è¿ä¸ªæ¯å¨ ââRFC 4646âââ æ åå®ä¹çï¼å¯ä»¥æ ¹æ®è¯è¨æ¿å°ãå ³äº zh-CN è¿ä¸ªè¯è¨æ ¼å¼çæ åï¼è¯·ç ââBCP47ââ æ å
private static string GetScript(StringValue language)
{
if (language == "zh-CN")
{
return "Hans";
}
else if (language == "zh-Hant")
{
return "Hant";
}
// é»è®¤å¼ï¼å½ç¶ï¼å¨ Office éé¢çé»è¾æ¯ååå¤çï¼éè¦æ ¹æ® [å½å®¶-å°åºå符串](https://docs.microsoft.com/zh-CN/cpp/c-runtime-library/country-region-strings?view=vs-2019 ) ææ¡£å代ç ï¼åªæ¯è¿é¨å代ç ä¸æ¯æ¬æéç¹
return "Hans";
}
ä¸é¢æ¯ç®åçé»è¾ï¼æ´å¤ä»£ç å°±éè¦ä½ å»éè¿ ââRFC 4646ââ æ åå»å代ç äº
å¨ä½¿ç¨ GetScript è¿åäº scriptTag å符串ä¹åï¼å°±å¯ä»¥å¨ FontCollectionType éåè·ååä½
private static string GetFontFromFontCollection(string scriptTag, FontLang themeTypefaceFontLang,
FontCollectionType fontCollection)
{
if (fontCollection == null)
{
return string.Empty;
}
// åå®åå¨å¯¹åºçè¯è¨çåä½ï¼é£ä¹è·å对åºçåä½
// åæ¾æ¹å¼å¦
/*
<a:majorFont xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:latin typeface="Calibri Light" panose="020F0302020204030204" />
<a:ea typeface="" />
<a:cs typeface="" />
<a:font script="Jpan" typeface="ï¼ï¼³ ï¼°ã´ã·ãã¯" />
<a:font script="Hang" typeface="ë§ì ê³ ë" />
<a:font script="Hans" typeface="å®ä½" />
</a:majorFont>
<a:minorFont xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:latin typeface="Calibri" panose="020F0502020204030204" />
<a:ea typeface="" />
<a:cs typeface="" />
<a:font script="Jpan" typeface="ï¼ï¼³ ï¼°ã´ã·ãã¯" />
<a:font script="Hang" typeface="ë§ì ê³ ë" />
<a:font script="Hans" typeface="å®ä½" />
</a:minorFont>
*/
foreach (var font in fontCollection.Elements<SupplementalFont>())
{
// <a:font script="Hang" typeface="ë§ì ê³ ë" />
if (string.Equals(font.Script, scriptTag, StringComparison.OrdinalIgnoreCase))
{
return font.Typeface;
}
}
// 忽ç¥ä»£ç
}
æ¤æ¶ç代ç æ¾å¨ ââgithubââ 欢è¿å°ä¼ä¼´è®¿é®ï¼æ¤æ¶å°±è½æ¿å°åä½
å¦ææ¤æ¶ç Theme1.xml å®ä¹æ¯å¦ä¸å¢
<a:minorFont>
<a:latin typeface="Calibri" panose="020F0502020204030204"/>
<a:ea typeface="æå¾·ç"/>
<a:cs typeface=""/>
<a:font script="Jpan" typeface="ï¼ï¼³ ï¼°ã´ã·ãã¯"/>
<a:font script="Hang" typeface="ë§ì ê³ ë"/>
<!-- <a:font script="Hans" typeface="éæ¯"/>-->
</a:minorFont>
ä¹å°±æ¯ font ç script æ¯ Hans çå®ä¹æ¯ä¸åå¨çï¼é£ä¹æ¤æ¶çè§åæ¯ä»ä¹ï¼æ¤æ¶çè§åå°±æ¯ FontLang 对åºçå 容
// ä¹å°±æ¯å
å°è¯è·åè¯è¨æåçï¼å¦æè·åä¸å°ï¼å°±éç¨å¯¹åºè¯è¨ç
TextFontType textFont = null;
switch (themeTypefaceFontLang)
{
case FontLang.LatinFont:
textFont = fontCollection.LatinFont;
break;
case FontLang.EastAsianFont:
textFont = fontCollection.EastAsianFont;
break;
case FontLang.ComplexScriptFont:
textFont = fontCollection.ComplexScriptFont;
break;
case FontLang.SymbolFont:
// ç¹å«ä¸å¤çï¼ä¸ºä»ä¹ï¼
// å¨ fontCollection æ¯ä¸åå¨ç SymbolFont ç
break;
default:
throw new ArgumentOutOfRangeException(nameof(themeTypefaceFontLang), themeTypefaceFontLang, null);
}
var typeface = textFont?.Typeface?.Value;
if (!string.IsNullOrEmpty(typeface))
{
return typeface;
}
Debug.Assert(false, "æ¾ä¸å°åä½");
return null;
å ¶å®è¿ä¸ªæ¾ä¸å°åä½ â
âDebug.Assert(false, "æ¾ä¸å°åä½")â
â çè¾åºä¹ä¸å ¨å¯¹ï¼å¦æ Theme1.xml å®ä¹æ¯å¦ä¸
<a:minorFont>
<a:latin typeface="csdn" panose="020F0502020204030204"/>
<a:ea typeface=""/>
<a:cs typeface=""/>
<a:font script="Jpan" typeface="ï¼ï¼³ ï¼°ã´ã·ãã¯"/>
<a:font script="Hang" typeface="ë§ì ê³ ë"/>
<!-- <a:font script="Hans" typeface="éæ¯"/>-->
</a:minorFont>
ä¹å°±æ¯ Hans 没æè¿ä¸ªå®ä¹ï¼è ea ä¹æ²¡æå¼ï¼æ¤æ¶å°ä¼éçº§ä½¿ç¨ latin çåä½
â
â
å¦æ latin ä¹æ²¡æå 容å¢ï¼å°ä½¿ç¨æ¬æºçé»è®¤è¯è¨åä½
ä½å°ä¼ä¼´æ¯å¦è§å¾ä¸é¢è¿æä¸ä¸ªæ²¡æç¨å°çå±æ§ï¼æ²¡éå°±æ¯ altLang è¿ä¸ªå±æ§
<a:p>
<a:r>
<a:rPr lang="zh-CN" altLang="en-US" sz="2000" smtClean="0"/>
<a:t>ä¸è¡ææ¬</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
è¿ä¸ªå±æ§æ¯åä»ä¹ç¨çï¼è¿æ¯ä¸ä¸ªå¤ç¨çå±æ§ï¼æç § ECMA-376 ç 21.1.2.3.2 defRPr (Default Text Run Properties) è¿ä¸ç« çæè¿°ï¼è¿æ¯ä¸ä¸ªå¤ç¨çå±æ§ï¼é»è®¤æ¯ä¸åçï¼ä¸åçæ¶åå°ä¼ä½¿ç¨ lang å±æ§ãè¿ä¸ªå±æ§å¯ä»¥ç¨æ¥æ¾ç¤ºçé¢æ§ä»¶æ¶ä½¿ç¨çå¤ç¨è¯è¨ï¼ä¹å°±æ¯å¨ lang æ¾ä¸å°è¯è¨çæ¶åï¼éè¦å¯ç¨ altLang å±æ§å»è·å
èå®é ä¸æ¬æçè§å主è¦é对 PPT èä¸æ¯ OpenXML ç ECMA-376 çæ åï¼å 为å®é ä¸ PPT æäºè¡ä¸ºå ECMA-376 ä¸ç¸åï¼æè 说æ没æç解对 ECMA-376 çææãèè¿é¨åä¹æ¯ OpenXML SDK 没ææä¾æ¥å£æ¹æ³ç
以ä¸æ¯ ECMA-376 çåæ
17.15.1.88 ThemeFontLang (Theme Font Languages)
These mappings are performed as follows:
- For majorAscii/majorHAnsi, locate the font element (§20.1.4.1.16) in the majorFont element (§20.1.4.1.24) in the theme part for the language specified by the val attribute
- For majorBidi, locate the font element in the majorFont element in the theme part for the language specified by the bidi attribute
- For majorEastAsia, locate the font element in the majorFont element in the theme part for the language specified by the eastAsia attribute
- For minorAscii/minorHAnsi, locate the font element in the minorFont element (§20.1.4.1.25) in the theme part for the language specified by the val attribute
- For minorBidi, locate the font element in the minorFont element in the theme part for the language specified by the bidi attribute
- For minorEastAsia, locate the font element in the minorFont element in the theme part for the language specified by the eastAsia attribute
If this element is omitted, then the default fonts for each region as specified by the latin, ea, and cs elements (§21.1.2.3.7; §21.1.2.3.3; §21.1.2.3.1) should be used
ä¸è¿ PPT 没ææç §ææ¡£å
ä¸ä¿¡ä½ è¯è¯ MinorAscii çå符ï¼ä¹å°±æ¯ Latin å符å®é ä¸æ¯ä¸éµå®ä¸é¢çè§å®çãè¿åçæ¯ Theme ç latin åä½
<a:p>
<a:r>
<a:rPr lang="ja-JP" altLang="en-US" sz="2000" smtClean="0"/>
<a:t>lindexi</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
<a:minorFont>
<a:latin typeface="Wingdings" panose="020F0502020204030204"/>
<a:ea typeface=""/>
<a:cs typeface=""/>
<a:font script="Jpan" typeface="微软é
é»"/>
<a:font script="Hang" typeface="ë§ì ê³ ë"/>
<a:font script="Hans" typeface="éæ¯"/>
</a:minorFont>
â
â
å¯ä»¥çå°è±æå符ç¨çæ¯ â
âa:latinâ
â çï¼èä¸æ¯ä½¿ç¨è¯è¨ç
æ´å¤è¯·ç Office ä½¿ç¨ OpenXML SDK 解æææ¡£å客ç®å½
OOXML Hacking: Font Themes Complete - Brandwares
ææ建äºèªå·±çå客 https://blog.lindexi.com/ 欢è¿å¤§å®¶è®¿é®ï¼éé¢æå¾å¤æ°çå客ã