diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..cd7c902d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# SA1626: Single-line comments should not use documentation style slashes +dotnet_diagnostic.SA1626.severity = suggestion diff --git a/OpenXmlPowerTools.sln b/OpenXmlPowerTools.sln index 806dc01e..f076c94a 100644 --- a/OpenXmlPowerTools.sln +++ b/OpenXmlPowerTools.sln @@ -1,82 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2036 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33530.505 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenXmlPowerTools", "OpenXmlPowerTools\OpenXmlPowerTools.csproj", "{6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChartUpdater01", "OpenXmlPowerToolsExamples\ChartUpdater01\ChartUpdater01.csproj", "{1B03D24F-FB08-42E1-BB25-2D1BB907991B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder01", "OpenXmlPowerToolsExamples\DocumentBuilder01\DocumentBuilder01.csproj", "{A8A6FCF0-CA4F-4637-8E66-D86603B92204}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder02", "OpenXmlPowerToolsExamples\DocumentBuilder02\DocumentBuilder02.csproj", "{BF8153AA-C390-4D00-98F2-083DEFEC7094}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder03", "OpenXmlPowerToolsExamples\DocumentBuilder03\DocumentBuilder03.csproj", "{BE635672-D3FD-42C5-96E3-EDE50E05CE29}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder04", "OpenXmlPowerToolsExamples\DocumentBuilder04\DocumentBuilder04.csproj", "{CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FieldRetriever01", "OpenXmlPowerToolsExamples\FieldRetriever01\FieldRetriever01.csproj", "{E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FormattingAssembler01", "OpenXmlPowerToolsExamples\FormattingAssembler01\FormattingAssembler01.csproj", "{6EAF15B6-98BE-428B-A018-A5266521551E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Formulas01", "OpenXmlPowerToolsExamples\Formulas01\Formulas01.csproj", "{618B95DB-3A70-4DC8-BD87-00F636F72453}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlConverter01", "OpenXmlPowerToolsExamples\HtmlConverter01\HtmlConverter01.csproj", "{BC9E7408-508D-482D-8602-96E76ACBB5EA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ListItemRetriever01", "OpenXmlPowerToolsExamples\ListItemRetriever01\ListItemRetriever01.csproj", "{04935FA6-E48B-496F-8D6A-41A59232303D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MarkupSimplifierApp", "OpenXmlPowerToolsExamples\MarkupSimplifierApp\MarkupSimplifierApp.csproj", "{0CCE83BA-8B8B-4B98-8846-B62A61FDF170}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetricsGetter01", "OpenXmlPowerToolsExamples\MetricsGetter01\MetricsGetter01.csproj", "{ED37372C-DFBF-4720-BD4B-CE1415961038}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenXmlRegex01", "OpenXmlPowerToolsExamples\OpenXmlRegex01\OpenXmlRegex01.csproj", "{4330D46F-6703-4BA2-844D-177F722C0820}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PivotTables01", "OpenXmlPowerToolsExamples\PivotTables01\PivotTables01.csproj", "{6785A554-BBBB-480C-8E4D-9FE90DD91A46}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PresentationBuilder01", "OpenXmlPowerToolsExamples\PresentationBuilder01\PresentationBuilder01.csproj", "{A4128935-B707-4D56-B924-27910EC92664}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PresentationBuilder02", "OpenXmlPowerToolsExamples\PresentationBuilder02\PresentationBuilder02.csproj", "{495060B4-BD80-4B18-AC44-4680F0D6D5DB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReferenceAdder01", "OpenXmlPowerToolsExamples\ReferenceAdder01\ReferenceAdder01.csproj", "{211F05D3-F8EE-497F-9DE9-AFFA0A72140D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevisionAccepter01", "OpenXmlPowerToolsExamples\RevisionAccepter01\RevisionAccepter01.csproj", "{84823BA5-B860-4CAF-885E-981D7F121830}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextReplacer01", "OpenXmlPowerToolsExamples\TextReplacer01\TextReplacer01.csproj", "{5CA29B44-C4A5-4310-9429-553F0BC9FC1D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextReplacer02", "OpenXmlPowerToolsExamples\TextReplacer02\TextReplacer02.csproj", "{153E5218-E9C0-4ED8-9073-0802204C8B90}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler01", "OpenXmlPowerToolsExamples\DocumentAssembler01\DocumentAssembler01.csproj", "{EFE77658-EDD7-4597-8016-CBE4A18951B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler", "OpenXmlPowerToolsExamples\DocumentAssembler\DocumentAssembler.csproj", "{2D081A36-48F9-4A09-8247-420682545492}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpreadsheetWriter01", "OpenXmlPowerToolsExamples\SpreadsheetWriter01\SpreadsheetWriter01.csproj", "{0911F996-DF86-4FB1-A1CE-0539599EC0E0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpreadsheetWriter02", "OpenXmlPowerToolsExamples\SpreadsheetWriter02\SpreadsheetWriter02.csproj", "{DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenXmlPowerTools.Tests", "OpenXmlPowerTools.Tests\OpenXmlPowerTools.Tests.csproj", "{B1328B70-33B8-40E0-A729-38C34D659B5C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler02", "OpenXmlPowerToolsExamples\DocumentAssembler02\DocumentAssembler02.csproj", "{D6DFAC7C-82F4-4318-A9F0-6450D2945D96}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlToWmlConverter01", "OpenXmlPowerToolsExamples\HtmlToWmlConverter01\HtmlToWmlConverter01.csproj", "{9E194D13-F5A0-4430-8F87-D74326457385}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler03", "OpenXmlPowerToolsExamples\DocumentAssembler03\DocumentAssembler03.csproj", "{214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlToWmlConverter02", "OpenXmlPowerToolsExamples\HtmlToWmlConverter02\HtmlToWmlConverter02.csproj", "{1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlToHtmlConverter01", "OpenXmlPowerToolsExamples\WmlToHtmlConverter01\WmlToHtmlConverter01.csproj", "{396D9209-0D9A-4E61-9471-04C71F6CA6B9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlToHtmlConverter02", "OpenXmlPowerToolsExamples\WmlToHtmlConverter02\WmlToHtmlConverter02.csproj", "{D4078011-2611-46A7-8A30-55E4AB8FA786}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmlDataRetriever01", "OpenXmlPowerToolsExamples\SmlDataRetriever01\SmlDataRetriever01.csproj", "{DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlComparer01", "OpenXmlPowerToolsExamples\WmlComparer01\WmlComparer01.csproj", "{C9CAA69C-575A-442E-9D8A-69C53B39D72C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlComparer02", "OpenXmlPowerToolsExamples\WmlComparer02\WmlComparer02.csproj", "{3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{A83D6B58-6D38-46AF-8C20-5CFC170A1063}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9AFB8C96-1E6E-483E-9882-75D2483E7076}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets LICENSE.txt = LICENSE.txt @@ -95,181 +26,10 @@ Global {6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}.Release|Any CPU.Build.0 = Release|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Release|Any CPU.Build.0 = Release|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Release|Any CPU.Build.0 = Release|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Release|Any CPU.Build.0 = Release|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Release|Any CPU.Build.0 = Release|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Release|Any CPU.Build.0 = Release|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Release|Any CPU.Build.0 = Release|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Release|Any CPU.Build.0 = Release|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Debug|Any CPU.Build.0 = Debug|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Release|Any CPU.ActiveCfg = Release|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Release|Any CPU.Build.0 = Release|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Release|Any CPU.Build.0 = Release|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Release|Any CPU.Build.0 = Release|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Release|Any CPU.Build.0 = Release|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Release|Any CPU.Build.0 = Release|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Release|Any CPU.Build.0 = Release|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Release|Any CPU.Build.0 = Release|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Release|Any CPU.Build.0 = Release|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Release|Any CPU.Build.0 = Release|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Release|Any CPU.Build.0 = Release|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Debug|Any CPU.Build.0 = Debug|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Release|Any CPU.ActiveCfg = Release|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Release|Any CPU.Build.0 = Release|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Release|Any CPU.Build.0 = Release|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Debug|Any CPU.Build.0 = Debug|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Release|Any CPU.ActiveCfg = Release|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Release|Any CPU.Build.0 = Release|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Release|Any CPU.Build.0 = Release|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Release|Any CPU.Build.0 = Release|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Release|Any CPU.Build.0 = Release|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Release|Any CPU.Build.0 = Release|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Release|Any CPU.Build.0 = Release|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Release|Any CPU.Build.0 = Release|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Release|Any CPU.Build.0 = Release|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Release|Any CPU.Build.0 = Release|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Release|Any CPU.Build.0 = Release|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Release|Any CPU.Build.0 = Release|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Release|Any CPU.Build.0 = Release|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Release|Any CPU.Build.0 = Release|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Release|Any CPU.Build.0 = Release|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {1B03D24F-FB08-42E1-BB25-2D1BB907991B} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {A8A6FCF0-CA4F-4637-8E66-D86603B92204} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {BF8153AA-C390-4D00-98F2-083DEFEC7094} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {BE635672-D3FD-42C5-96E3-EDE50E05CE29} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {6EAF15B6-98BE-428B-A018-A5266521551E} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {618B95DB-3A70-4DC8-BD87-00F636F72453} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {BC9E7408-508D-482D-8602-96E76ACBB5EA} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {04935FA6-E48B-496F-8D6A-41A59232303D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {ED37372C-DFBF-4720-BD4B-CE1415961038} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {4330D46F-6703-4BA2-844D-177F722C0820} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {6785A554-BBBB-480C-8E4D-9FE90DD91A46} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {A4128935-B707-4D56-B924-27910EC92664} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {495060B4-BD80-4B18-AC44-4680F0D6D5DB} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {84823BA5-B860-4CAF-885E-981D7F121830} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {153E5218-E9C0-4ED8-9073-0802204C8B90} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {EFE77658-EDD7-4597-8016-CBE4A18951B0} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {2D081A36-48F9-4A09-8247-420682545492} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {0911F996-DF86-4FB1-A1CE-0539599EC0E0} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {9E194D13-F5A0-4430-8F87-D74326457385} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {396D9209-0D9A-4E61-9471-04C71F6CA6B9} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {D4078011-2611-46A7-8A30-55E4AB8FA786} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {C9CAA69C-575A-442E-9D8A-69C53B39D72C} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E623EFF5-2CA4-4FA0-B3AB-53F921DA212E} EndGlobalSection diff --git a/OpenXmlPowerTools/ChartUpdater.cs b/OpenXmlPowerTools/ChartUpdater.cs index 79b0f74b..908c3fab 100644 --- a/OpenXmlPowerTools/ChartUpdater.cs +++ b/OpenXmlPowerTools/ChartUpdater.cs @@ -58,6 +58,12 @@ public class ChartData public string[] CategoryNames; public double[][] Values; + + /// + /// 组合图表中,次轴图表的序列名称映射 + /// 映射规则为:chatData中的序列名对应模板中的序列名。 + /// + public Dictionary SecondChartSeriesNames { get; set; } = new Dictionary(); } public class ChartUpdater @@ -94,7 +100,14 @@ public static void UpdateChart(ChartPart chartPart, ChartData chartData) throw new ArgumentException("Invalid chart data"); } + UpdateEmbeddedWorkbook(chartPart, chartData); + UpdateSeries(chartPart, chartData); + //如果设置了次轴,更新次轴 + if (chartData.SecondChartSeriesNames.Count > 0) + { + UpdateSeries(chartPart, chartData, true); + } } private static Dictionary FormatCodes = new Dictionary() @@ -129,13 +142,44 @@ public static void UpdateChart(ChartPart chartPart, ChartData chartData) { 49, "@" }, }; - private static void UpdateSeries(ChartPart chartPart, ChartData chartData) + /// + /// + /// + /// + /// + /// 设置次级坐标,默认为false + /// + private static void UpdateSeries(ChartPart chartPart, ChartData chartData, bool setSecond = false) { - UpdateEmbeddedWorkbook(chartPart, chartData); - + // update series XDocument cpXDoc = chartPart.GetXDocument(); XElement root = cpXDoc.Root; - var firstSeries = root.Descendants(C.ser).FirstOrDefault(); + + // 序列名 + var seriesNames = chartData.SeriesNames.Except(chartData.SecondChartSeriesNames.Keys); + if (setSecond) + { + seriesNames = chartData.SecondChartSeriesNames.Keys; + } + + var series = root.Descendants(C.ser).ToList(); + // 如果不处理次轴 + if (!setSecond) + { + series = series.Where(x => x.Descendants(C.tx).SelectMany(tx => tx.Descendants(C.v)).Any(v => !chartData.SecondChartSeriesNames.Values.Contains(v.Value))).ToList(); + + if (series == null || series.Count == 0) + throw new OpenXmlPowerToolsException("未找到图表主序列"); + } + else // 处理次轴 + { + series = series.Where(x => x.Descendants(C.tx).SelectMany(tx => tx.Descendants(C.v)).Any(v => chartData.SecondChartSeriesNames.Values.Contains(v.Value))).ToList(); + + if (series == null || series.Count == 0) + throw new OpenXmlPowerToolsException("未找到次轴序列,请检查次轴映射字典"); + } + + var firstSeries = series.FirstOrDefault(); var numRef = firstSeries.Elements(C.val).Elements(C.numRef).FirstOrDefault(); string sheetName = null; var f = (string)firstSeries.Descendants(C.f).FirstOrDefault(); @@ -151,6 +195,9 @@ private static void UpdateSeries(ChartPart chartPart, ChartData chartData) { XElement cat = null; + if (!seriesNames.Contains(sn)) + return null; + var oldCat = firstSeries.Elements(C.cat).FirstOrDefault(); if (oldCat == null) throw new OpenXmlPowerToolsException("Invalid chart markup"); @@ -379,6 +426,10 @@ private static void UpdateSeries(ChartPart chartPart, ChartData chartData) newSer = (XElement)UpdateAccentTransform(newSer, accentNumber); return newSer; }); + + // 删除newSetOfSeries中null的项目 + newSetOfSeries = newSetOfSeries.Where(x => x != null).ToList(); + firstSeries.ReplaceWith(newSetOfSeries); chartPart.PutXDocument(); } @@ -427,7 +478,7 @@ private static void UpdateEmbeddedWorkbook(ChartPart chartPart, ChartData chartD var firstRow = new XElement(S.row, new XAttribute("r", "1"), new XAttribute("spans", string.Format("1:{0}", chartData.SeriesNames.Length + 1)), - new [] { new XElement(S.c, + new[] { new XElement(S.c, new XAttribute("r", "A1"), new XAttribute("t", "str"), new XElement(S.v, diff --git a/OpenXmlPowerTools/DocumentAssembler.cs b/OpenXmlPowerTools/DocumentAssembler.cs index f4d9673e..1a1f724d 100644 --- a/OpenXmlPowerTools/DocumentAssembler.cs +++ b/OpenXmlPowerTools/DocumentAssembler.cs @@ -483,6 +483,7 @@ private static string ValidatePerSchema(XElement element) + ", @@ -575,6 +576,8 @@ private class PA public static XName Match = "Match"; public static XName NotMatch = "NotMatch"; public static XName Depth = "Depth"; + + public static XName HeaderRowCount = "HeaderRowCount"; } private class PASchemaSet @@ -600,8 +603,8 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr XElement para = element.Descendants(W.p).FirstOrDefault(); XElement run = element.Descendants(W.r).FirstOrDefault(); - var xPath = (string) element.Attribute(PA.Select); - var optionalString = (string) element.Attribute(PA.Optional); + var xPath = (string)element.Attribute(PA.Select); + var optionalString = (string)element.Attribute(PA.Optional); bool optional = (optionalString != null && optionalString.ToLower() == "true"); string newValue; @@ -618,7 +621,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr { XElement p = new XElement(W.p, para.Elements(W.pPr)); - foreach(string line in newValue.Split('\n')) + foreach (string line in newValue.Split('\n')) { p.Add(new XElement(W.r, para.Elements(W.r).Elements(W.rPr).FirstOrDefault(), @@ -630,7 +633,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr else { List list = new List(); - foreach(string line in newValue.Split('\n')) + foreach (string line in newValue.Split('\n')) { list.Add(new XElement(W.r, run.Elements().Where(e => e.Name != W.t), @@ -692,11 +695,21 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr } if (tableData.Count() == 0) return CreateContextErrorMessage(element, "Table Select returned no data", templateError); + + + + int? headerRowCountAttr = (int?)element.Attribute(PA.HeaderRowCount) ?? 1; + if (headerRowCountAttr.Value < 1) + { + headerRowCountAttr = 1; + } + var headerRowCount = headerRowCountAttr.Value; + XElement table = element.Element(W.tbl); - XElement protoRow = table.Elements(W.tr).Skip(1).FirstOrDefault(); + XElement protoRow = table.Elements(W.tr).Skip(headerRowCount).FirstOrDefault(); var footerRowsBeforeTransform = table .Elements(W.tr) - .Skip(2) + .Skip(headerRowCount + 1) .ToList(); var footerRows = footerRowsBeforeTransform .Select(x => ContentReplacementTransform(x, data, templateError)) @@ -707,7 +720,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr protoRow.Descendants(W.bookmarkEnd).Remove(); XElement newTable = new XElement(W.tbl, table.Elements().Where(e => e.Name != W.tr), - table.Elements(W.tr).FirstOrDefault(), + table.Elements(W.tr).Take(headerRowCount), tableData.Select(d => new XElement(W.tr, protoRow.Elements().Where(r => r.Name != W.tc), @@ -756,17 +769,17 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr if (match != null && notMatch != null) return CreateContextErrorMessage(element, "Conditional: Cannot specify both Match and NotMatch", templateError); - string testValue = null; - + string testValue = null; + try { testValue = EvaluateXPathToString(data, xPath, false); } - catch (XPathException e) + catch (XPathException e) { return CreateContextErrorMessage(element, e.Message, templateError); } - + if ((match != null && testValue == match) || (notMatch != null && testValue != notMatch)) { var content = element.Elements().Select(e => ContentReplacementTransform(e, data, templateError)); @@ -815,14 +828,14 @@ private static XElement CreateParaErrorMessage(string errorMessage, TemplateErro return errorPara; } - private static string EvaluateXPathToString(XElement element, string xPath, bool optional ) + private static string EvaluateXPathToString(XElement element, string xPath, bool optional) { object xPathSelectResult; try { //support some cells in the table may not have an xpath expression. if (String.IsNullOrWhiteSpace(xPath)) return String.Empty; - + xPathSelectResult = element.XPathEvaluate(xPath); } catch (XPathException e) @@ -832,7 +845,7 @@ private static string EvaluateXPathToString(XElement element, string xPath, bool if ((xPathSelectResult is IEnumerable) && !(xPathSelectResult is string)) { - var selectedData = ((IEnumerable) xPathSelectResult).Cast(); + var selectedData = ((IEnumerable)xPathSelectResult).Cast(); if (!selectedData.Any()) { if (optional) return string.Empty; @@ -843,11 +856,11 @@ private static string EvaluateXPathToString(XElement element, string xPath, bool throw new XPathException(string.Format("XPath expression ({0}) returned more than one node", xPath)); } - XObject selectedDatum = selectedData.First(); - - if (selectedDatum is XElement) return ((XElement) selectedDatum).Value; + XObject selectedDatum = selectedData.First(); + + if (selectedDatum is XElement) return ((XElement)selectedDatum).Value; - if (selectedDatum is XAttribute) return ((XAttribute) selectedDatum).Value; + if (selectedDatum is XAttribute) return ((XAttribute)selectedDatum).Value; } return xPathSelectResult.ToString(); diff --git a/OpenXmlPowerTools/GlobalSuppressions.cs b/OpenXmlPowerTools/GlobalSuppressions.cs new file mode 100644 index 00000000..64410479 --- /dev/null +++ b/OpenXmlPowerTools/GlobalSuppressions.cs @@ -0,0 +1,20 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; +[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1004:Documentation lines should begin with single space", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1612:Element parameter documentation should match element parameters", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1616:Element return value documentation should have text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1617:Void return value should not be documented", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1614:Element parameter documentation should have text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1627:Documentation text should not be empty", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1606:Element documentation should have summary text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1629:Documentation text should end with a period", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1514:Element documentation header should be preceded by blank line", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1626:Single-line comments should not use documentation style slashes", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1636:File header copyright text should match", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1642:Constructor summary documentation should begin with standard text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File should have header", Justification = "<挂起>")] diff --git a/OpenXmlPowerTools/Helpers/ImageHelper.cs b/OpenXmlPowerTools/Helpers/ImageHelper.cs new file mode 100644 index 00000000..822f28d9 --- /dev/null +++ b/OpenXmlPowerTools/Helpers/ImageHelper.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace OpenXmlPowerTools.Helpers +{ + public class ImageHelper + { + public static (int width, int height) GetImageMetrics(Stream imageData, ImageFormat imageFormat) + { + var width = 0; + var height = 0; + + if (imageFormat == ImageFormat.Emf) + { + using (var metafile = new Metafile(imageData)) + { + width = metafile.Width; // 获取宽度 + height = metafile.Height; // 获取高度 + } + } + else + { + using (var image = Image.FromStream(imageData)) + { + width = image.Width; // 获取宽度 + height = image.Height; // 获取高度 + } + } + + return (width, height); + } + + /// + /// 获取图片的宽和高 + /// + /// + /// + public static (int width, int height) GetImageMetrics(string newImagePath, ImageFormat imageFormat) + { + var ext = Path.GetExtension(newImagePath).ToLower(); + var stream = File.OpenRead(newImagePath); + return GetImageMetrics(stream, imageFormat); + } + } +} diff --git a/OpenXmlPowerTools/ImageReplacer.cs b/OpenXmlPowerTools/ImageReplacer.cs new file mode 100644 index 00000000..579fea53 --- /dev/null +++ b/OpenXmlPowerTools/ImageReplacer.cs @@ -0,0 +1,245 @@ +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Wordprocessing; +using OpenXmlPowerTools.Helpers; +using System; +using System.Collections.Generic; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace OpenXmlPowerTools +{ + /// + /// 图片替换器 + /// + public class ImageUpdater + { + private readonly ImageFormat _imageFormat; + + /// + /// 设置的宽度,可以为百分比,如果不填则默认使用页面宽度 + /// + private readonly string _width; + + /// + /// 设置高度,可以为百分比,如果不填则根据宽度缩放后自适应 + /// + private readonly string _height; + + public byte[] ImageBytes { get; private set; } + + /// + /// 图片替换器构造函数 + /// + /// 新图片的字节数组 + public ImageUpdater(byte[] imageBytes, ImageFormat imageFormat, string width = null, string height = null) + { + ImageBytes = imageBytes; + _imageFormat = imageFormat; + _width = width; + _height = height; + } + + /// + /// 新图片路径 + /// + /// + public ImageUpdater(string newImagePath, ImageFormat imageFormat, string width = null, string height = null) + { + ImageBytes = File.ReadAllBytes(newImagePath); + _imageFormat = imageFormat; + _width = width; + _height = height; + } + + /// + /// 替换图片 + /// + /// Word文档对象 + /// 要替换的控件tag + /// 新图片的路径 + /// + public static bool ReplaceImage(WordprocessingDocument wDoc, + string contentControlTag, + string newImagePath, + ImageFormat imageFormat, + string width = null, + string height = null) + { + var replacer = new ImageUpdater(newImagePath, imageFormat, width, height); + return replacer.Replace(wDoc, contentControlTag); + } + + /// + /// 替换图片 + /// + /// Word文档对象 + /// 要替换的控件tag + /// 新图片的路径 + /// + public static bool ReplaceImage(WordprocessingDocument wDoc, + string contentControlTag, + byte[] imageBytes, + ImageFormat imageFormat, + string width = null, + string height = null) + { + var replacer = new ImageUpdater(imageBytes, imageFormat, width, height); + return replacer.Replace(wDoc, contentControlTag); + } + + /// + /// 替换图片 + /// + /// + /// + /// + private bool Replace(WordprocessingDocument wDoc, string contentControlTag) + { + var mainDocumentPart = wDoc.MainDocumentPart; + var mdXDoc = mainDocumentPart.GetXDocument(); + var cc = mdXDoc.Descendants(W.sdt) + .FirstOrDefault(sdt => (string)sdt.Elements(W.sdtPr).Elements(W.tag).Attributes(W.val).FirstOrDefault() == contentControlTag); + + if (cc != null) + { + // 替换imagePart + var imageId = (string)cc.Descendants(A.blip).Attributes(R.embed).FirstOrDefault(); + + if (imageId != null) + { + ImagePart imagePart = (ImagePart)mainDocumentPart.GetPartById(imageId); + ReplaceNewImage(imagePart, this.ImageBytes); + } + + // 修改宽度和高度 + UpdateImageMetrics(mdXDoc, cc); + + // 替换cc + var paragraph = cc.Descendants(W.sdtContent).Descendants(W.p).FirstOrDefault(); + if (paragraph != null) + { + cc.ReplaceWith(paragraph); + } + + mainDocumentPart.PutXDocument(); + return true; + } + + return false; + } + + /// + /// 更新图片宽高 + /// + /// + private void UpdateImageMetrics(XDocument mdXDoc, XElement cc) + { + float dpi = 96; + + // 得到图片宽高 + var imgStream = new MemoryStream(this.ImageBytes); + var (imgWidth, imgHeight) = ImageHelper.GetImageMetrics(imgStream, this._imageFormat); + + // 得到页面宽高 + double pageWidth = 0; + double pageHeight = 0; + + var pageSize = mdXDoc.Descendants(W.sectPr).FirstOrDefault()?.Descendants(W.pgSz).FirstOrDefault(); + if (pageSize != null) + { + pageWidth = Convert.ToDouble(pageSize.Attribute(W.w.GetName("w")).Value) / 20; + pageHeight = Convert.ToDouble(pageSize.Attribute(W.w.GetName("h")).Value) / 20; + } + + // 得到设置宽高,传进来的参数 + int.TryParse(this._width, out var settingWidth); + int.TryParse(this._height, out var settingHeight); + + // 如果设置的宽度是百分比,那么按百分比计算宽度 + if (this._width != null && this._width.EndsWith("%")) + { + // 先计算比例,避免宽度变更后比例也跟着变化。 + var radio = imgWidth / (float)imgHeight; + double percent = Convert.ToDouble(this._width.TrimEnd('%')) / 100; + imgWidth = (int)(pageWidth * percent); + + // 如果没有设置高度,那么按比例计算高度 + if (this._height == null) + { + // 那么按比例计算高度 + imgHeight = (int)(imgWidth / radio); + } + } + else if (settingWidth > 0) // 如果设置了宽度,那么按设置的宽度来 + { + imgWidth = settingWidth; + } + + // 如果度是百分比,那么按百分比计算高度 + if (this._height != null && this._height.EndsWith("%")) + { + // 先计算比例,避免宽度变更后比例也跟着变化。 + var radio = imgWidth / (float)imgHeight; + double percent = Convert.ToDouble(this._height.TrimEnd('%')) / 100; + imgHeight = (int)(pageHeight * percent); + + // 如果没有设置宽度,那么按比例计算宽度 + if (this._width == null) + { + // 那么按比例计算宽度 + imgWidth = (int)(imgHeight * radio); + } + } + else if (settingHeight > 0) // 如果设置了高度,那么按设置的高度来 + { + imgHeight = settingHeight; + } + + // 换算成EMUS + var cx = (long)(imgWidth / dpi * 914400); + var cy = (long)(imgHeight / dpi * 914400); + + var drawing = cc.Descendants(W.drawing).FirstOrDefault(); + if (drawing != null) + { + var extent = drawing.Descendants(WP.extent).FirstOrDefault(); + if (extent != null) + { + extent.SetAttributeValue("cx", cx); + extent.SetAttributeValue("cy", cy); + } + var aExtent = drawing.Descendants(A.graphic).Descendants(Pic.spPr).Descendants(A.ext).FirstOrDefault(); + if (aExtent != null) + { + aExtent.SetAttributeValue("cx", cx); + aExtent.SetAttributeValue("cy", cy); + } + } + } + + // 按比例缩放图片的方法,传入图片原始宽度和高度,传入缩放后的宽度 + private static (int width, int height) ScaleImage(int originalWidth, int originalHeight, int scaledWidth) + { + var ratio = (float)originalWidth / originalHeight; + var scaledHeight = (int)(scaledWidth / ratio); + return (scaledWidth, scaledHeight); + } + + /// + /// 替换新图片 + /// + /// + /// + private void ReplaceNewImage(ImagePart imagePart, byte[] imageBytes) + { + var stream = imagePart.GetStream(); + + BinaryWriter writer = new BinaryWriter(stream); + writer.Write(imageBytes); + writer.Close(); + } + } +} diff --git a/OpenXmlPowerTools/NugetPush.bat b/OpenXmlPowerTools/NugetPush.bat new file mode 100644 index 00000000..33e81789 --- /dev/null +++ b/OpenXmlPowerTools/NugetPush.bat @@ -0,0 +1,4 @@ +del .\bin\Release\*.nupkg +dotnet pack -o ./bin/release +dotnet nuget push .\bin\Release\*.nupkg -k 123.123a -s http://nuget.cefcfco.com +pause \ No newline at end of file diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index c7220506..53c99d63 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,6 +1,12 @@  - net45;net46;netstandard2.0 + netstandard2.0 + 4.5.10.5 + yitian.chen + yitian.chen + OpenXmlPowerTools-HrRd + true + True diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs index 5811c0e4..cf4a2027 100644 --- a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs +++ b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs @@ -14,6 +14,46 @@ namespace OpenXmlPowerTools class Program { static void Main(string[] args) + { + // Example1(); + TowTypeChartExample(); + } + + private static void TowTypeChartExample() + { + var fi = new FileInfo("TowTypeChart.docx"); + + using (var wDoc = WordprocessingDocument.Open(fi.FullName, true)) + { + var chart1Data = new ChartData + { + SecondChartType = C.lineChart, + SecondChartSeriesIndex = new[] { 1 }, + SeriesNames = new[] { + "平仓手数", + "平仓盈亏-逐笔对冲", + }, + CategoryDataType = ChartDataType.String, + CategoryNames = new[] { + "1:0天", + "1:1天", + "1:2天", + "1:3天", + }, + Values = new double[][] { + new double[] { + 100, 310, 220, 450, + }, + new double[] { + -11323.65, 3101, -12220, 15421, + }, + }, + }; + ChartUpdater.UpdateChart(wDoc, "towTypeChart", chart1Data); + } + } + + private static void Example1() { var n = DateTime.Now; var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second)); diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj index e188d465..5bd48a12 100644 --- a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj +++ b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj @@ -12,4 +12,10 @@ + + + + Always + + \ No newline at end of file diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/TowTypeChart.docx b/OpenXmlPowerToolsExamples/ChartUpdater01/TowTypeChart.docx new file mode 100644 index 00000000..5e4ae532 Binary files /dev/null and b/OpenXmlPowerToolsExamples/ChartUpdater01/TowTypeChart.docx differ diff --git a/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml b/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml index 64cc21e5..2ab6983a 100644 --- a/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml +++ b/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml @@ -15,4 +15,21 @@ September 26, 2001 + + + Items1 + 1 + 10 + + + Items2 + 2 + 15 + + + Items3 + 3 + 30 + + \ No newline at end of file diff --git a/OpenXmlPowerToolsExamples/DocumentAssembler02/TemplateDocument.docx b/OpenXmlPowerToolsExamples/DocumentAssembler02/TemplateDocument.docx index 45e8c994..3b45793a 100644 Binary files a/OpenXmlPowerToolsExamples/DocumentAssembler02/TemplateDocument.docx and b/OpenXmlPowerToolsExamples/DocumentAssembler02/TemplateDocument.docx differ diff --git a/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj b/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj index e188d465..5f593cb0 100644 --- a/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj +++ b/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj @@ -3,6 +3,9 @@ Exe net45;net46;netcoreapp2.0 + + + diff --git a/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj b/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj index 90ae7ebe..ff153d40 100644 --- a/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj +++ b/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj @@ -15,9 +15,7 @@ - - Form - + Form