Browse Source

Merge branch 'develop' into develop_local

jeff 11 tháng trước cách đây
mục cha
commit
4ce15a8130
100 tập tin đã thay đổi với 3069 bổ sung2100 xóa
  1. 0 2
      TEAMModelBI/Controllers/BICommon/BINoticeController.cs
  2. 0 1
      TEAMModelBI/Controllers/BICommon/StatsNoticeController.cs
  3. 1 2
      TEAMModelBI/Controllers/BINormal/AbilityMgmtController.cs
  4. 1 1
      TEAMModelBI/Controllers/BINormal/AbilityTaskMgmtController.cs
  5. 0 2
      TEAMModelBI/Controllers/BINormal/BatchAreaController.cs
  6. 0 6
      TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs
  7. 0 1
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  8. 0 1
      TEAMModelBI/Controllers/BIServer/BiServersController.cs
  9. 0 1
      TEAMModelBI/Controllers/BITable/IES5OAuthController.cs
  10. 0 2
      TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs
  11. 0 4
      TEAMModelBI/Controllers/BITest/TestController.cs
  12. 0 1
      TEAMModelBI/Controllers/BITmid/TmidController.cs
  13. 0 1
      TEAMModelBI/Controllers/Census/ItemSticsController.cs
  14. 0 2
      TEAMModelBI/Controllers/Census/PaperController.cs
  15. 0 1
      TEAMModelBI/Controllers/LoginController.cs
  16. 0 3
      TEAMModelBI/Controllers/RepairApi/InitialAreaController.cs
  17. 0 2
      TEAMModelBI/Controllers/RepairApi/SchoolRepController.cs
  18. 0 2
      TEAMModelBI/Filter/RequestAuditFilter.cs
  19. 1 2
      TEAMModelBI/Models/ItemInfo.cs
  20. 3 3
      TEAMModelBI/TEAMModelBI.csproj
  21. 0 2
      TEAMModelBI/Tool/CommonFind.cs
  22. 1 2
      TEAMModelBI/Tool/TimeHelper1.cs
  23. 12 12
      TEAMModelContest/contest.client/src/locale/lang/en-US.js
  24. 11 11
      TEAMModelContest/contest.client/src/locale/lang/zh-TW.js
  25. 1 1
      TEAMModelOS.Function/.gitignore
  26. 0 1
      TEAMModelOS.Function/CosmosDBTriggers/TriggerArt.cs
  27. 1 1
      TEAMModelOS.Function/CosmosDBTriggers/TriggerCorrect.cs
  28. 3 9
      TEAMModelOS.Function/CosmosDBTriggers/TriggerExam.cs
  29. 0 1
      TEAMModelOS.Function/CosmosDBTriggers/TriggerExamImport.cs
  30. 0 1
      TEAMModelOS.Function/CosmosDBTriggers/TriggerExamLite.cs
  31. 0 1
      TEAMModelOS.Function/CosmosDBTriggers/TriggerHomework.cs
  32. 0 2
      TEAMModelOS.Function/CosmosDBTriggers/TriggerQuotaImport.cs
  33. 1 6
      TEAMModelOS.Function/CosmosDBTriggers/TriggerStudy.cs
  34. 0 1
      TEAMModelOS.Function/CosmosDBTriggers/TriggerSurvey.cs
  35. 2 3
      TEAMModelOS.Function/CosmosDBTriggers/TriggerVote.cs
  36. 2 1
      TEAMModelOS.Function/IESCosmosDBTrigger.cs
  37. 0 1
      TEAMModelOS.Function/IESHttpTrigger.cs
  38. 0 1
      TEAMModelOS.Function/IESServiceBusTrigger.cs
  39. 9 0
      TEAMModelOS.Function/TEAMModelOS.Function.csproj
  40. 2 1
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/ChartUpdater.cs
  41. 2 1
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/ComparisonUnitAtom.cs
  42. 1 1
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/ComparisonUnitWord.cs
  43. 3 1
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Internal.Methods.ComparisonUnits.cs
  44. 3 2
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.Hashing.cs
  45. 1 0
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.Lcs.cs
  46. 9 2
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.ProduceDocument.cs
  47. 2 2
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.Util.cs
  48. 1 0
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Public.Methods.Compare.cs
  49. 4 3
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Public.Methods.Consolidate.cs
  50. 1 0
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Public.Methods.GetRevisions.cs
  51. 0 27
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparerExtensions.cs
  52. 0 29
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparerSettings.cs
  53. 1 26
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparerUtil.cs
  54. 13 2
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/DocumentBuilder.cs
  55. 3 1
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/FieldRetriever.cs
  56. 255 10
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/FormattingAssembler.cs
  57. 2 0
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/HtmlToWmlConverterCore.cs
  58. 20 17
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/ListItemRetriever.cs
  59. 273 211
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/MarkupSimplifier.cs
  60. 2 2
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/MetricsGetter.cs
  61. 1 1
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PresentationBuilder.cs
  62. 226 162
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PtOpenXmlDocument.cs
  63. 294 143
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PtOpenXmlUtil.cs
  64. 239 26
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PtUtil.cs
  65. 1147 912
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/RevisionProcessor.cs
  66. 33 24
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/TestUtil.cs
  67. 5 9
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/UnicodeMapper.cs
  68. 2 2
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/WORDHelper.cs
  69. 373 155
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Properties/WmlComparer.cs
  70. 22 21
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/WmlToHtmlConverter.cs
  71. 2 2
      TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/XlsxTables.cs
  72. 0 5
      TEAMModelOS.HTEXLib/PPTX/Controller/HtexController.cs
  73. 0 67
      TEAMModelOS.HTEXLib/PPTX/Helpers/ShapeHelpers/JsonHelper.cs
  74. 2 2
      TEAMModelOS.HTEXLib/PPTX/Helpers/ShapeHelpers/PPTXHelper.cs
  75. 2 7
      TEAMModelOS.HTEXLib/TEAMModelOS.HTEXLib.csproj
  76. 2 2
      TEAMModelOS.HTEXLib/Translator/HTML2ITEMV2Translator.cs
  77. 4 2
      TEAMModelOS.HTEXLib/Translator/HTML2ITEMV3Translator.cs
  78. 1 1
      TEAMModelOS.SDK/Context/Attributes/Filter/ApiTokenAttribute.cs
  79. 1 1
      TEAMModelOS.SDK/DI/AzureCosmos/Inner/SQLHelper.cs
  80. 2 8
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs
  81. 0 1
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs
  82. 2 13
      TEAMModelOS.SDK/DI/CoreAPI/CoreAPIHttpService.cs
  83. 0 1
      TEAMModelOS.SDK/DI/DingDing/DingDing.cs
  84. 1 17
      TEAMModelOS.SDK/DI/HttpTrigger/WebHookHttpTrigger.cs
  85. 1 6
      TEAMModelOS.SDK/DI/Mail/MailFactory.cs
  86. 1 10
      TEAMModelOS.SDK/DI/StudyAPI/ScsStudyApisService.cs
  87. 0 12
      TEAMModelOS.SDK/Extension/CoreTokenExtensions.cs
  88. 43 0
      TEAMModelOS.SDK/Helper/Common/CollectionHelper/CollectionHelper.cs
  89. 2 2
      TEAMModelOS.SDK/Helper/Common/ReflectorExtensions/ObjectCopyConvert.cs
  90. 1 3
      TEAMModelOS.SDK/Helper/Common/TaskAll/BatchTask.cs
  91. 1 1
      TEAMModelOS.SDK/Helper/Security/ShaHash/ShaHashHelper.cs
  92. 1 7
      TEAMModelOS.SDK/Models/Cosmos/School/ExamImport.cs
  93. 0 7
      TEAMModelOS.SDK/Models/Cosmos/School/ExamInfo.cs
  94. 1 6
      TEAMModelOS.SDK/Models/Cosmos/School/IotStatistics.cs
  95. 1 6
      TEAMModelOS.SDK/Models/Cosmos/School/ScoreCalc.cs
  96. 7 10
      TEAMModelOS.SDK/Models/Dtos/ItemDto.cs
  97. 1 8
      TEAMModelOS.SDK/Models/Dtos/LessonRecordActivityInfo.cs
  98. 1 2
      TEAMModelOS.SDK/Models/Dtos/ShanDa/Field.cs
  99. 0 1
      TEAMModelOS.SDK/Models/Service/Analysis/AchievementService.cs
  100. 0 0
      TEAMModelOS.SDK/Models/Service/ArtService.cs

+ 0 - 2
TEAMModelBI/Controllers/BICommon/BINoticeController.cs

@@ -23,8 +23,6 @@ using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
 using TEAMModelBI.Tool.Extension;
 using TEAMModelOS.SDK.Models;
-using DocumentFormat.OpenXml.Spreadsheet;
-using System.Net.Http.Json;
 
 namespace TEAMModelBI.Controllers.BICommon
 {

+ 0 - 1
TEAMModelBI/Controllers/BICommon/StatsNoticeController.cs

@@ -16,7 +16,6 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BICommon;
 using System.Collections.Generic;
 using System.Text;
-using DocumentFormat.OpenXml.Office2010.Excel;
 
 namespace TEAMModelBI.Controllers.BICommon
 {

+ 1 - 2
TEAMModelBI/Controllers/BINormal/AbilityMgmtController.cs

@@ -11,13 +11,12 @@ using TEAMModelOS.Models;
 using Microsoft.Extensions.Options;
 using System.Text.Json;
 using Azure.Cosmos;
-using HTEXLib.COMM.Helpers;
 using System.Text;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelBI.Filter;
 using TEAMModelBI.Tool.Extension;
 using TEAMModelOS.SDK.Context.BI;
-
+using TEAMModelOS.SDK;
 namespace TEAMModelBI.Controllers.BINormal
 {
     [Route("biabilitymgmt")]

+ 1 - 1
TEAMModelBI/Controllers/BINormal/AbilityTaskMgmtController.cs

@@ -11,7 +11,6 @@ using Microsoft.Extensions.Options;
 using System.Text.Json;
 using TEAMModelOS.SDK.Models;
 using Azure.Cosmos;
-using HTEXLib.COMM.Helpers;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using System.Text;
 using TEAMModelBI.Filter;
@@ -19,6 +18,7 @@ using TEAMModelOS.SDK.Services;
 using TEAMModelBI.Tool.Extension;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Context.BI;
+using TEAMModelOS.SDK;
 
 namespace TEAMModelBI.Controllers.BINormal
 {

+ 0 - 2
TEAMModelBI/Controllers/BINormal/BatchAreaController.cs

@@ -11,7 +11,6 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Models;
 using Azure.Cosmos;
 using System.Text.Json;
-using HTEXLib.COMM.Helpers;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using Azure.Messaging.ServiceBus;
@@ -28,7 +27,6 @@ using System.Net;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Context.BI;
 using System.Text;
-using DocumentFormat.OpenXml.Bibliography;
 using Microsoft.Extensions.Hosting;
 using Microsoft.AspNetCore.Hosting;
 using TEAMModelOS.SDK.Context.Constant;

+ 0 - 6
TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs

@@ -1,5 +1,4 @@
 using Azure.Cosmos;
-using HTEXLib.COMM.Helpers;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -32,13 +31,8 @@ using TEAMModelOS.SDK.Context.Constant;
 using Pipelines.Sockets.Unofficial.Arenas;
 using Microsoft.Identity.Client;
 using TEAMModelOS.SDK.Models.Dtos;
-using DocumentFormat.OpenXml.Spreadsheet;
-using DocumentFormat.OpenXml.Wordprocessing;
-using DocumentFormat.OpenXml.Bibliography;
-using HTEXLib;
 using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
-using DocumentFormat.OpenXml.Vml.Office;
 using System.Net.Http.Headers;
 using System.Text.Encodings.Web;
 using System.ComponentModel.DataAnnotations;

+ 0 - 1
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -1,5 +1,4 @@
 using Azure.Cosmos;
-using HTEXLib.COMM.Helpers;
 using MathNet.Numerics.LinearAlgebra.Double;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;

+ 0 - 1
TEAMModelBI/Controllers/BIServer/BiServersController.cs

@@ -13,7 +13,6 @@ using System.Net.Http;
 using TEAMModelOS.SDK.Extension;
 using System.Text;
 using System.Net;
-using HTEXLib.COMM.Helpers;
 using System.Net.Http.Json;
 using TEAMModelOS.SDK;
 using TEAMModelBI.Filter;

+ 0 - 1
TEAMModelBI/Controllers/BITable/IES5OAuthController.cs

@@ -1,6 +1,5 @@
 using Azure.Cosmos;
 using Azure.Storage.Blobs;
-using DocumentFormat.OpenXml.Spreadsheet;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;

+ 0 - 2
TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs

@@ -17,7 +17,6 @@ using System.Net.Http.Json;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using System.Net;
 using TEAMModelOS.SDK.Extension;
-using OpenXmlPowerTools;
 using System.Text;
 using Azure.Cosmos;
 using Microsoft.Azure.Cosmos.Table;
@@ -30,7 +29,6 @@ using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.Models.Dtos;
-using DocumentFormat.OpenXml.Bibliography;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
 
 namespace TEAMModelBI.Controllers.BITable

+ 0 - 4
TEAMModelBI/Controllers/BITest/TestController.cs

@@ -2,7 +2,6 @@
 using DingTalk.Api;
 using DingTalk.Api.Request;
 using DingTalk.Api.Response;
-using HTEXLib.COMM.Helpers;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
@@ -53,12 +52,9 @@ using Azure.Storage.Blobs;
 using Azure.Storage.Blobs.Specialized;
 using System.Web;
 using Azure.Storage.Sas;
-using DocumentFormat.OpenXml.Drawing.Diagrams;
-using DocumentFormat.OpenXml.Bibliography;
 using TEAMModelOS.SDK.Models.Service.BIStatsWay;
 using MathNet.Numerics.LinearAlgebra.Double;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
-using DocumentFormat.OpenXml.Drawing;
 using Microsoft.OData.Edm;
 using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BICommon;

+ 0 - 1
TEAMModelBI/Controllers/BITmid/TmidController.cs

@@ -1,5 +1,4 @@
 using Azure.Cosmos;
-using DocumentFormat.OpenXml.Office2010.Excel;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Azure.Cosmos.Table;

+ 0 - 1
TEAMModelBI/Controllers/Census/ItemSticsController.cs

@@ -16,7 +16,6 @@ using TEAMModelOS.SDK.Context.BI;
 using Azure.Core;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Context.Constant;
-using DocumentFormat.OpenXml.Wordprocessing;
 using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census

+ 0 - 2
TEAMModelBI/Controllers/Census/PaperController.cs

@@ -2,7 +2,6 @@
 using Azure.Storage.Blobs;
 using Azure.Storage.Blobs.Models;
 using Azure.Storage.Sas;
-using DocumentFormat.OpenXml.Drawing.Diagrams;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -23,7 +22,6 @@ using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
-using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;

+ 0 - 1
TEAMModelBI/Controllers/LoginController.cs

@@ -12,7 +12,6 @@ using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Models;
-using HTEXLib.COMM.Helpers;
 using TEAMModelOS.Models;
 using Microsoft.Extensions.Options;
 using TEAMModelOS.SDK.Extension;

+ 0 - 3
TEAMModelBI/Controllers/RepairApi/InitialAreaController.cs

@@ -20,9 +20,6 @@ using System.Collections.Generic;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using System.Linq;
 using Pipelines.Sockets.Unofficial.Arenas;
-using TEAMModelOS.SDK.Models.Cosmos.BI;
-using TEAMModelBI.Filter;
-using HTEXLib.COMM.Helpers;
 using TEAMModelBI.Models;
 
 namespace TEAMModelBI.Controllers.RepairApi

+ 0 - 2
TEAMModelBI/Controllers/RepairApi/SchoolRepController.cs

@@ -23,9 +23,7 @@ using Pipelines.Sockets.Unofficial.Arenas;
 using TEAMModelBI.Tool;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
-using DocumentFormat.OpenXml.Math;
 using TEAMModelOS.SDK.Models.Service.BI;
-using TEAMModelBI.Tool.CosmosBank;
 using TEAMModelOS.SDK.Models.Service.BIStatsWay;
 using StackExchange.Redis;
 using System.Text.RegularExpressions;

+ 0 - 2
TEAMModelBI/Filter/RequestAuditFilter.cs

@@ -11,14 +11,12 @@ using System.Linq;
 using Azure.Core;
 using TEAMModelOS.SDK.DI;
 using Microsoft.Extensions.Primitives;
-using HTEXLib.Helpers.ShapeHelpers;
 using System.Net.Http;
 using System.ServiceModel.Channels;
 using System.Net;
 using System.Net.Http.Json;
 using Microsoft.Extensions.Options;
 using TEAMModelOS.Models;
-using OpenXmlPowerTools;
 
 namespace TEAMModelOS.Filter
 {

+ 1 - 2
TEAMModelBI/Models/ItemInfo.cs

@@ -1,5 +1,4 @@
-using DocumentFormat.OpenXml.Office2010.ExcelAc;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using TEAMModelOS.SDK.Models;
 
 namespace TEAMModelBI.Models

+ 3 - 3
TEAMModelBI/TEAMModelBI.csproj

@@ -65,9 +65,9 @@
 		<SpaRoot>ClientApp\</SpaRoot>
 		<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
 		<UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-		<Version>5.2406.26</Version>
-		<AssemblyVersion>5.2406.26.1</AssemblyVersion>
-		<FileVersion>5.2406.26.1</FileVersion>
+		<Version>5.2407.3</Version>
+		<AssemblyVersion>5.2407.3.1</AssemblyVersion>
+		<FileVersion>5.2407.3.1</FileVersion>
 		<Description>TEAMModelBI(BI)</Description>
 		<PackageReleaseNotes>BI版本说明版本切换标记2022000908</PackageReleaseNotes>
 		<PackageId>TEAMModelBI</PackageId>

+ 0 - 2
TEAMModelBI/Tool/CommonFind.cs

@@ -1,5 +1,4 @@
 using Azure.Cosmos;
-using DocumentFormat.OpenXml.Spreadsheet;
 using System;
 using System.Collections.Generic;
 using System.Text;
@@ -7,7 +6,6 @@ using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelBI.Models;
 using TEAMModelOS.SDK.Models;
-using TEAMModelOS.SDK.Models.Cosmos.Common;
 
 namespace TEAMModelBI.Tool
 {

+ 1 - 2
TEAMModelBI/Tool/TimeHelper1.cs

@@ -1,5 +1,4 @@
-using DocumentFormat.OpenXml.Bibliography;
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;

+ 12 - 12
TEAMModelContest/contest.client/src/locale/lang/en-US.js

@@ -135,22 +135,22 @@ const enUS = {
         scoring: "Please rate",
     },
     elMessage: {
-        logout: "已退出登录",
-        noRoute: "未匹配分站",
+        logout: "Logged out",
+        noRoute: "No matching station",
         noAct: "No activity yet",
-        teamTips: "本次活动为团队赛,请创建团队或加入团队",
+        teamTips: "This event is a team competition, please create a team or join a team",
         videomsg: "Your browser does not support the video tag",
         audiomsg: "Your browser does not support the audio element",
         completeInfo: "Please complete the information",
-        signcompInfo: "报名信息未完善",
-        schoolJoin: "请以学校教师身份参加本次活动",
-        diffTeam: "参加组别不一致",
-        notAct: "活动不存在",
-        notFindTeam: "未找到相关团队信息",
-        noTeam: "队伍未组建或不存在",
-        schoolDiff: "报名学校与组队学校不一致",
-        signOvertime: "已过报名时间",
-        uploadOverTime: "上传作品时间已过",
+        signcompInfo: "Registration is not complete",
+        schoolJoin: "Please participate in this event as a school teacher",
+        diffTeam: "Participating groups are inconsistent",
+        notAct: "The event does not exist",
+        notFindTeam: "No relevant team information found",
+        noTeam: "The team has not been formed or does not exist",
+        schoolDiff: "The registered school is inconsistent with the team forming school",
+        signOvertime: "The registration time has passed",
+        uploadOverTime: "The time for uploading works has passed",
         joinSuccess: "报名成功",
         joinError: "报名失败",
         joinAct: "已经报名该活动",

+ 11 - 11
TEAMModelContest/contest.client/src/locale/lang/zh-TW.js

@@ -135,22 +135,22 @@ const zhTW = {
         scoring: "請打分數",
     },
     elMessage: {
-        logout: "已退出登录",
+        logout: "已登出",
         noRoute: "未匹配分站",
         noAct: "暫無活動",
-        teamTips: "本次活动为团队赛,请创建团队或加入团队",
+        teamTips: "本次活動為團隊賽,請建立或加入團隊",
         videomsg: "您的瀏覽器不支援 video 標籤。",
         audiomsg: "您的瀏覽器不支援 audio 元素。",
         completeInfo: "請完善資訊",
-        signcompInfo: "报名信息未完善",
-        schoolJoin: "请以学校教师身份参加本次活动",
-        diffTeam: "参加组别不一致",
-        notAct: "活不存在",
-        notFindTeam: "未找到相关团队信息",
-        noTeam: "队伍未组建或不存在",
-        schoolDiff: "报名学校与组队学校不一致",
-        signOvertime: "已过报名时间",
-        uploadOverTime: "上传作品时间已过",
+        signcompInfo: "報名資料未完善",
+        schoolJoin: "請以學校教師身份參加本次活動",
+        diffTeam: "參加組別不一致",
+        notAct: "活不存在",
+        notFindTeam: "未找到相關團隊資訊",
+        noTeam: "隊伍未組成或不存在",
+        schoolDiff: "報名的學校與組隊學校不一致",
+        signOvertime: "已過了報名時間",
+        uploadOverTime: "上傳作品時間已過",
         joinSuccess: "报名成功",
         joinError: "报名失败",
         joinAct: "已经报名该活动",

+ 1 - 1
TEAMModelOS.Function/.gitignore

@@ -2,7 +2,7 @@
 ## files generated by popular Visual Studio add-ons.
 
 # Azure Functions localsettings file
-local.settings.json
+#local.settings.json
 
 # User-specific files
 *.suo

+ 0 - 1
TEAMModelOS.Function/CosmosDBTriggers/TriggerArt.cs

@@ -1,5 +1,4 @@
 using Azure.Messaging.ServiceBus;
-using HTEXLib.COMM.Helpers;
 using Microsoft.Extensions.Configuration;
 using System;
 using System.Collections.Generic;

+ 1 - 1
TEAMModelOS.Function/CosmosDBTriggers/TriggerCorrect.cs

@@ -7,7 +7,7 @@ using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
-using HTEXLib.COMM.Helpers;
+ 
 using TEAMModelOS.Function;
 
 

+ 3 - 9
TEAMModelOS.Function/CosmosDBTriggers/TriggerExam.cs

@@ -5,7 +5,6 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Service;
-using HTEXLib.COMM.Helpers;
 using ClouDASLibx;
 using System.Text.Json;
 using System.Collections.Generic;
@@ -19,18 +18,13 @@ using System.Text;
 using System.Text.Json.Nodes;
 using Newtonsoft.Json.Linq;
 using TEAMModelOS.SDK.Models.Cosmos.Student;
-using HTEXLib.Helpers.ShapeHelpers;
 using TEAMModelOS.Models.Dto;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
-using DocumentFormat.OpenXml.Office2010.Excel;
-using DocumentFormat.OpenXml.Drawing.Charts;
-using DocumentFormat.OpenXml.Vml;
 using System.Net.Http;
 using Newtonsoft.Json;
 using System.Net;
 using System.Security.Policy;
 using Microsoft.Extensions.Configuration;
-using DocumentFormat.OpenXml.EMMA;
 using Microsoft.Extensions.Options;
 using TEAMModelOS.Models;
 using Microsoft.AspNetCore.Razor.TagHelpers;
@@ -201,7 +195,7 @@ namespace TEAMModelOS.CosmosDBTriggers
                                         foreach (ExamSubject subject in info.subjects)
                                         {
                                             string classCode = string.Empty;
-                                            string cname = string.Empty;
+                                            string? cname = string.Empty;
                                             if (string.IsNullOrEmpty(info.school) || !info.scope.Equals("school", StringComparison.OrdinalIgnoreCase))
                                             {
                                                 classCode = "ExamClassResult-" + info.creatorId;
@@ -1089,8 +1083,8 @@ namespace TEAMModelOS.CosmosDBTriggers
                 //确定高分组 最低分数
                 //var srowallorder = scores.EnumerateIndexed().OrderByDescending(g => g.Item2); //各生總分排序   
                 //var srowallorder =  scores.OrderByDescending(g => g);
-                double[] point = StringHelper.ListTodouble(er.paper.point);
-                double[,] result = StringHelper.ListToDouble(er.studentScores);
+                double[] point = TEAMModelOS.SDK.Helper.Common.StringHelper.StringHelper.ListTodouble(er.paper.point);
+                double[,] result = TEAMModelOS.SDK.Helper.Common.StringHelper. StringHelper.ListToDouble(er.studentScores);
                 var cdm = new ClouDASMatrix(result, point);
 
                 scores.Sort((s1, s2) => { return s2.CompareTo(s1); });

+ 0 - 1
TEAMModelOS.Function/CosmosDBTriggers/TriggerExamImport.cs

@@ -12,7 +12,6 @@ using System.Net.Http;
 using TEAMModelOS.SDK.Models.Cosmos.School;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
-using HTEXLib.COMM.Helpers;
 using TEAMModelOS.Function;
 namespace TEAMModelOS.CosmosDBTriggers
 {

+ 0 - 1
TEAMModelOS.Function/CosmosDBTriggers/TriggerExamLite.cs

@@ -1,6 +1,5 @@
 using Azure.Cosmos;
 using Azure.Messaging.ServiceBus;
-using HTEXLib.COMM.Helpers;
 using Microsoft.Azure.Documents;
 using Microsoft.Extensions.Configuration;
 using System;

+ 0 - 1
TEAMModelOS.Function/CosmosDBTriggers/TriggerHomework.cs

@@ -1,6 +1,5 @@
 using Azure.Cosmos;
 using Azure.Messaging.ServiceBus;
-using HTEXLib.COMM.Helpers;
 using Microsoft.Azure.Documents;
 using Microsoft.Extensions.Configuration;
 using System;

+ 0 - 2
TEAMModelOS.Function/CosmosDBTriggers/TriggerQuotaImport.cs

@@ -12,8 +12,6 @@ using Azure.Cosmos;
 using TEAMModelOS.SDK.Models.Cosmos.School;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Extension;
-using HTEXLib.COMM.Helpers;
-using OpenXmlPowerTools;
 using Microsoft.OData.Edm;
 using TEAMModelOS.Function;
 namespace TEAMModelOS.CosmosDBTriggers

+ 1 - 6
TEAMModelOS.Function/CosmosDBTriggers/TriggerStudy.cs

@@ -1,11 +1,6 @@
 using Azure.Cosmos;
 using Azure.Messaging.ServiceBus;
-using DocumentFormat.OpenXml.Bibliography;
-using DocumentFormat.OpenXml.Office2013.Excel;
-using DocumentFormat.OpenXml.Spreadsheet;
-using DocumentFormat.OpenXml.VariantTypes;
-using DocumentFormat.OpenXml.Vml;
-using HTEXLib.COMM.Helpers;
+ 
 using Microsoft.Azure.Documents;
 using Microsoft.Extensions.Configuration;
 using System;

+ 0 - 1
TEAMModelOS.Function/CosmosDBTriggers/TriggerSurvey.cs

@@ -18,7 +18,6 @@ using TEAMModelOS.SDK.Models.Cosmos.Common;
 using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
 using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
 using TEAMModelOS.SDK.Models.Service;
-using HTEXLib.COMM.Helpers;
 using Microsoft.Extensions.Configuration;
 using System.Linq;
 using TEAMModelOS.SDK.Models.Service.BI;

+ 2 - 3
TEAMModelOS.Function/CosmosDBTriggers/TriggerVote.cs

@@ -15,10 +15,9 @@ using TEAMModelOS.SDK.Models.Cosmos;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
 using TEAMModelOS.SDK.Models.Service;
-using HTEXLib.COMM.Helpers;
+ 
 using Microsoft.Extensions.Configuration;
-using DocumentFormat.OpenXml.Office2013.Excel;
-using DocumentFormat.OpenXml.Vml;
+ 
 using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.Function;
 namespace TEAMModelOS.CosmosDBTriggers

+ 2 - 1
TEAMModelOS.Function/IESCosmosDBTrigger.cs

@@ -45,7 +45,8 @@ namespace TEAMModelOS.Function
             databaseName: "TEAMModelOS",
             containerName: "Common",
             Connection = "Azure:Cosmos:ConnectionString",
-            LeaseContainerName = "leases",
+            LeaseDatabaseName ="Lease",
+            LeaseContainerName = "lease",
             LeaseContainerPrefix = "TEAMModelOS",
             CreateLeaseContainerIfNotExists = true,StartFromBeginning =false)] IReadOnlyList<JsonElement> input)
         {

+ 0 - 1
TEAMModelOS.Function/IESHttpTrigger.cs

@@ -11,7 +11,6 @@ using Microsoft.Extensions.Options;
 using System.Net;
 using System.Text.Json;
 using System.Reflection;
-using HTEXLib.COMM.Helpers;
 using StackExchange.Redis;
 using static TEAMModelOS.SDK.Services.BlobService;
 using TEAMModelOS.SDK.Models;

+ 0 - 1
TEAMModelOS.Function/IESServiceBusTrigger.cs

@@ -20,7 +20,6 @@ using TEAMModelOS.SDK.Models.Cosmos.Common;
 using StackExchange.Redis;
 using static TEAMModelOS.SDK.StatisticsService;
 using Azure;
-using HTEXLib.COMM.Helpers;
 using TEAMModelOS.SDK.Models.Dtos;
 using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Service;

+ 9 - 0
TEAMModelOS.Function/TEAMModelOS.Function.csproj

@@ -5,6 +5,15 @@
     <OutputType>Exe</OutputType>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
+	<Version>5.2407.3</Version>
+	<AssemblyVersion>5.2407.3.1</AssemblyVersion>
+	<FileVersion>5.2407.3.1</FileVersion>
+	<PackageId>TEAMModelOS.FunctionV4</PackageId>
+	<Authors>teammodel</Authors>
+	<Company>醍摩豆(成都)信息技术有限公司</Company>
+	<Product>IES5</Product>
+	<Description>事件触发中心 </Description>
+	<PackageProjectUrl>https://www.teammodel.cn/</PackageProjectUrl>
   </PropertyGroup>
   <ItemGroup>
     <None Remove="Lang\en-us.json" />

+ 2 - 1
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/ChartUpdater.cs

@@ -564,7 +564,8 @@ namespace OpenXmlPowerTools
 
         private static object UpdateAccentTransform(XNode node, int accentNumber)
         {
-            if (node is XElement element)
+            XElement element = node as XElement;
+            if (element != null)
             {
                 if (element.Name == A.schemeClr && (string)element.Attribute("val") == "accent1")
                     return new XElement(A.schemeClr, new XAttribute("val", "accent" + accentNumber));

+ 2 - 1
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/ComparisonUnitAtom.cs

@@ -6,6 +6,7 @@ using System.Linq;
 using System.Text;
 using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
+using OpenXmlPowerTools.Previous;
 
 namespace OpenXmlPowerTools
 {
@@ -46,7 +47,7 @@ namespace OpenXmlPowerTools
             else
             {
                 string shaHashString = GetSha1HashStringForElement(ContentElement, settings);
-                SHA1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaHashString);
+                SHA1Hash = PtUtils.SHA1HashStringForUTF8String(shaHashString);
             }
         }
 

+ 1 - 1
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/ComparisonUnitWord.cs

@@ -62,7 +62,7 @@ namespace OpenXmlPowerTools
         {
             Contents = comparisonUnitAtomList.OfType<ComparisonUnit>().ToList();
             string sha1String = Contents.Select(c => c.SHA1Hash).StringConcatenate();
-            SHA1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(sha1String);
+            SHA1Hash = PtUtils.SHA1HashStringForUTF8String(sha1String);
         }
 
         public override string ToString(int indent)

+ 3 - 1
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Internal.Methods.ComparisonUnits.cs

@@ -1,4 +1,5 @@
-// Copyright (c) Microsoft. All rights reserved.
+
+// Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 using System;
@@ -7,6 +8,7 @@ using System.Linq;
 using System.Text;
 using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
+using OpenXmlPowerTools.Previous;
 
 namespace OpenXmlPowerTools
 {

+ 3 - 2
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.Hashing.cs

@@ -7,6 +7,7 @@ using System.IO;
 using System.Linq;
 using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
+using OpenXmlPowerTools.Previous;
 
 namespace OpenXmlPowerTools
 {
@@ -52,7 +53,7 @@ namespace OpenXmlPowerTools
                             .ToString(SaveOptions.DisableFormatting)
                             .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", "");
 
-                        string sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaString);
+                        string sha1Hash = PtUtils.SHA1HashStringForUTF8String(shaString);
                         var thisUnid = (string) blockLevelContent.Attribute(PtOpenXml.Unid);
                         if (thisUnid != null)
                         {
@@ -229,7 +230,7 @@ namespace OpenXmlPowerTools
                                                     ba = br.ReadBytes((int) str.Length);
                                                 }
 
-                                                string sha1 = WmlComparerUtil.SHA1HashStringForByteArray(ba);
+                                                string sha1 = PtUtils.SHA1HashStringForByteArray(ba);
                                                 oxp.AddAnnotation(new PartSHA1HashAnnotation(sha1));
                                                 return new XAttribute(a.Name, sha1);
                                             }

+ 1 - 0
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.Lcs.cs

@@ -1,6 +1,7 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+using OpenXmlPowerTools.Previous;
 using System;
 using System.Collections.Generic;
 using System.Linq;

+ 9 - 2
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.ProduceDocument.cs

@@ -9,6 +9,7 @@ using System.Linq;
 using System.Text;
 using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
+using OpenXmlPowerTools.Previous;
 
 namespace OpenXmlPowerTools
 {
@@ -262,7 +263,7 @@ namespace OpenXmlPowerTools
                     (XElement) CloneBlockLevelContentForHashing(part, blockLevelContent, true, settings);
                 string shaString = cloneBlockLevelContentForHashing.ToString(SaveOptions.DisableFormatting)
                     .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", "");
-                string sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaString);
+                string sha1Hash = PtUtils.SHA1HashStringForUTF8String(shaString);
                 blockLevelContent.Add(new XAttribute(PtOpenXml.SHA1Hash, sha1Hash));
 
                 if (blockLevelContent.Name == W.tbl ||
@@ -277,7 +278,7 @@ namespace OpenXmlPowerTools
 
                     string shaString2 = clonedForStructureHash.ToString(SaveOptions.DisableFormatting)
                         .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", "");
-                    string sha1Hash2 = WmlComparerUtil.SHA1HashStringForUTF8String(shaString2);
+                    string sha1Hash2 = PtUtils.SHA1HashStringForUTF8String(shaString2);
                     blockLevelContent.Add(new XAttribute(PtOpenXml.StructureSHA1Hash, sha1Hash2));
                 }
             }
@@ -2747,11 +2748,17 @@ namespace OpenXmlPowerTools
                                         OpenXmlPart openXmlPartInNewDocument = part;
                                         return gc.Select(gce =>
                                         {
+
+
                                             Package packageOfDeletedContent = openXmlPartOfDeletedContent.OpenXmlPackage.Package;
+ 
                                             Package packageOfNewContent = openXmlPartInNewDocument.OpenXmlPackage.Package;
                                             PackagePart partInDeletedDocument = packageOfDeletedContent.GetPart(part.Uri);
                                             PackagePart partInNewDocument = packageOfNewContent.GetPart(part.Uri);
 
+
+                                            
+
                                             return MoveRelatedPartsToDestination(
                                                 partInDeletedDocument,
                                                 partInNewDocument,

+ 2 - 2
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Private.Methods.Util.cs

@@ -46,12 +46,12 @@ namespace OpenXmlPowerTools
                     string uriString;
                     if (last.Length == 2)
                     {
-                        uriString = uriSplit.SkipLast(1).Select(p => p + "/").StringConcatenate() +
+                        uriString = uriSplit.PtSkipLast(1).Select(p => p + "/").StringConcatenate() +
                                     "P" + Guid.NewGuid().ToString().Replace("-", "") + "." + last[1];
                     }
                     else
                     {
-                        uriString = uriSplit.SkipLast(1).Select(p => p + "/").StringConcatenate() +
+                        uriString = uriSplit.PtSkipLast(1).Select(p => p + "/").StringConcatenate() +
                                     "P" + Guid.NewGuid().ToString().Replace("-", "");
                     }
 

+ 1 - 0
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Public.Methods.Compare.cs

@@ -5,6 +5,7 @@ using System.IO;
 using System.Linq;
 using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
+using OpenXmlPowerTools.Previous;
 
 // It is possible to optimize DescendantContentAtoms
 

+ 4 - 3
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Public.Methods.Consolidate.cs

@@ -9,6 +9,7 @@ using System.Linq;
 using System.Text;
 using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
+using OpenXmlPowerTools.Previous;
 
 namespace OpenXmlPowerTools
 {
@@ -289,7 +290,7 @@ namespace OpenXmlPowerTools
                                     // Get a hash after first accepting revisions and compressing the text.
                                     XElement acceptedRevisionElement =
                                         RevisionProcessor.AcceptRevisionsForElement(ci.RevisionElement);
-                                    string sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(acceptedRevisionElement.Value
+                                    string sha1Hash = PtUtils.SHA1HashStringForUTF8String(acceptedRevisionElement.Value
                                         .Replace(" ", "").Replace(" ", "").Replace(" ", "").Replace("\n", "").Replace(".", "")
                                         .Replace(",", "").ToUpper());
                                     return sha1Hash;
@@ -384,7 +385,7 @@ namespace OpenXmlPowerTools
                                         .Replace(" ", "")
                                         .Replace(" ", "")
                                         .Replace("\n", "");
-                                    var sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(text);
+                                    var sha1Hash = PtUtils.SHA1HashStringForUTF8String(text);
                                     return ci.InsertBefore.ToString() + sha1Hash;
                                 })
                                 .OrderByDescending(g => g.Count())
@@ -890,7 +891,7 @@ namespace OpenXmlPowerTools
             clonedForHashing.Descendants().Where(d => d.Name == W.ins || d.Name == W.del).Attributes(W.id).Remove();
             string shaString = clonedForHashing.ToString(SaveOptions.DisableFormatting)
                 .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", "");
-            string sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaString);
+            string sha1Hash = PtUtils.SHA1HashStringForUTF8String(shaString);
             consolidationInfo.RevisionString = shaString;
             consolidationInfo.RevisionHash = sha1Hash;
 

+ 1 - 0
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparer.Public.Methods.GetRevisions.cs

@@ -8,6 +8,7 @@ using System.Linq;
 using System.Text;
 using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
+using OpenXmlPowerTools.Previous;
 
 namespace OpenXmlPowerTools
 {

+ 0 - 27
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparerExtensions.cs

@@ -1,27 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Xml.Linq;
-using DocumentFormat.OpenXml.Packaging;
-
-namespace OpenXmlPowerTools
-{
-    public static class WmlComparerExtensions
-    {
-        public static XElement GetMainDocumentBody(this WordprocessingDocument wordDocument)
-        {
-            return wordDocument.GetMainDocumentRoot().Element(W.body) ?? throw new ArgumentException("Invalid document.");
-        }
-
-        public static XElement GetMainDocumentRoot(this WordprocessingDocument wordDocument)
-        {
-            return wordDocument.MainDocumentPart?.GetXElement() ?? throw new ArgumentException("Invalid document.");
-        }
-
-        public static XElement GetXElement(this OpenXmlPart part)
-        {
-            return part.GetXDocument()?.Root ?? throw new ArgumentException("Invalid document.");
-        }
-    }
-}

+ 0 - 29
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparerSettings.cs

@@ -1,29 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Globalization;
-using System.IO;
-
-namespace OpenXmlPowerTools
-{
-    public class WmlComparerSettings
-    {
-        public char[] WordSeparators;
-        public string AuthorForRevisions = "Open-Xml-PowerTools";
-        public string DateTimeForRevisions = DateTime.Now.ToString("o");
-        public double DetailThreshold = 0.15;
-        public bool CaseInsensitive = false;
-        public CultureInfo CultureInfo = null;
-        public Action<string> LogCallback = null;
-        public int StartingIdForFootnotesEndnotes = 1;
-
-        public DirectoryInfo DebugTempFileDi;
-
-        public WmlComparerSettings()
-        {
-            // note that , and . are processed explicitly to handle cases where they are in a number or word
-            WordSeparators = new[] { ' ', '-', ')', '(', ';', ',' }; // todo need to fix this for complete list
-        }
-    }
-}

+ 1 - 26
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Comparer/WmlComparerUtil.cs

@@ -9,32 +9,7 @@ namespace OpenXmlPowerTools
 {
     internal static class WmlComparerUtil
     {
-        public static string SHA1HashStringForUTF8String(string s)
-        {
-            var bytes = Encoding.UTF8.GetBytes(s);
-            var sha1 = SHA1.Create();
-            var hashBytes = sha1.ComputeHash(bytes);
-            return HexStringFromBytes(hashBytes);
-        }
-
-        public static string SHA1HashStringForByteArray(byte[] bytes)
-        {
-            var sha1 = SHA1.Create();
-            var hashBytes = sha1.ComputeHash(bytes);
-            return HexStringFromBytes(hashBytes);
-        }
-
-        public static string HexStringFromBytes(byte[] bytes)
-        {
-            var sb = new StringBuilder();
-            foreach (var b in bytes)
-            {
-                var hex = b.ToString("x2");
-                sb.Append(hex);
-            }
-
-            return sb.ToString();
-        }
+       
 
         public static ComparisonUnitGroupType ComparisonUnitGroupTypeFromLocalName(string localName)
         {

+ 13 - 2
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/DocumentBuilder.cs

@@ -1829,6 +1829,14 @@ application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
             toLatentStyles.SetAttributeValue(W.count, count);
         }
 
+        private static void MergeDocDefaultStyles(XDocument xDocument, XDocument newXDoc)
+        {
+            var docDefaultStyles = xDocument.Descendants(W.docDefaults);
+            foreach (var docDefaultStyle in docDefaultStyles)
+            {
+                newXDoc.Root.Add(docDefaultStyle);
+            }
+        }
 
 #if MergeStylesWithSameNames
         private static void ConvertToNewId(XElement element, Dictionary<string, string> newIds)
@@ -3615,11 +3623,14 @@ application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
                 newXDoc.Add(new XElement(W.styles,
                     new XAttribute(XNamespace.Xmlns + "w", W.w),
                     stylesPart.GetXDocument().Descendants(W.docDefaults)
-                    
+                    //,
+                    //stylesPart.GetXDocument().Descendants(W.docDefaults)
+
                     //,
                     //new XElement(W.latentStyles, stylesPart.GetXDocument().Descendants(W.latentStyles).Attributes())
-                    
+
                     ));
+                MergeDocDefaultStyles(stylesPart.GetXDocument(), newXDoc);
                 MergeStyles(sourceDocument, newDocument, stylesPart.GetXDocument(), newXDoc, Enumerable.Empty<XElement>());
                 MergeLatentStyles(stylesPart.GetXDocument(), newXDoc);
             }

+ 3 - 1
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/FieldRetriever.cs

@@ -371,7 +371,9 @@ namespace OpenXmlPowerTools
             if (fieldType.ToUpper() != "HYPERLINK" &&
                 fieldType.ToUpper() != "REF" &&
                 fieldType.ToUpper() != "SEQ" &&
-                fieldType.ToUpper() != "STYLEREF")
+                fieldType.ToUpper() != "STYLEREF" &&
+                fieldType.ToUpper() != "LISTNUM" &&
+                fieldType.ToUpper() != "PAGE")
                 return emptyField;
             string[] tokens = GetTokens(field);
             if (tokens.Length == 0)

+ 255 - 10
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/FormattingAssembler.cs

@@ -232,6 +232,7 @@ namespace OpenXmlPowerTools
                         );
 
                         XElement listItemRunProps = null;
+                        List<XAttribute> listItemHtmlAttributes = new List<XAttribute>();
                         int? abstractNumId = null;
                         if (listItemInfo != null)
                         {
@@ -283,9 +284,33 @@ namespace OpenXmlPowerTools
                             var listItemLvlRunProps = listItemLvl.Elements(W.rPr).FirstOrDefault();
                             listItemRunProps = MergeStyleElement(listItemLvlRunProps, mergedRunProps);
 
-                            if ((string)listItemLvl.Elements(W.numFmt).Attributes(W.val).FirstOrDefault() == "bullet")
+                            string numFmt = null;
+                            string format = null;
+                            numFmt = (string)listItemLvl.Elements(W.numFmt).Attributes(W.val).FirstOrDefault();
+
+                            if (numFmt == null)
+                            {
+                                var mcAlternativeContent = listItemLvl.Descendants(MC.AlternateContent).FirstOrDefault();
+                                if (mcAlternativeContent != null)
+                                {
+                                    var choice = mcAlternativeContent.Element(MC.Choice);
+                                    if (choice != null)
+                                    {
+                                        numFmt = (string)choice.Elements(W.numFmt).Attributes(W.val).FirstOrDefault();
+                                        format = (string)choice.Elements(W.numFmt).Attributes(W.format).FirstOrDefault();
+                                    }
+                                }
+                            }
+
+                            if (numFmt == "bullet")
                             {
                                 listItemRunProps.Elements(W.rtl).Remove();
+                                listItemHtmlAttributes.Add(
+                                    new XAttribute(PtOpenXml.HtmlStructure, "ul")
+                                );
+                                listItemHtmlAttributes.Add(
+                                    new XAttribute(PtOpenXml.HtmlStyle, "list-style-type: circle;")
+                                );
                             }
                             else
                             {
@@ -300,6 +325,46 @@ namespace OpenXmlPowerTools
                                             new XElement(W.rtl)), listItemRunProps);
                                     }
                                 }
+                                listItemHtmlAttributes.Add(
+                                    new XAttribute(PtOpenXml.HtmlStructure, "ol")
+                                );
+
+                                if (numFmt == "decimal")
+                                {
+                                    listItemHtmlAttributes.Add(
+                                        new XAttribute(PtOpenXml.HtmlStyle, "list-style-type: decimal;")
+                                    );
+                                }
+                                else if (numFmt == "lowerLetter")
+                                {
+                                    listItemHtmlAttributes.Add(
+                                        new XAttribute(PtOpenXml.HtmlStyle, "list-style-type: lower-alpha;")
+                                    );
+                                }
+                                else if (numFmt == "lowerRoman")
+                                {
+                                    listItemHtmlAttributes.Add(
+                                        new XAttribute(PtOpenXml.HtmlStyle, "list-style-type: lower-roman;")
+                                    );
+                                }
+                                else if (numFmt == "upperLetter")
+                                {
+                                    listItemHtmlAttributes.Add(
+                                        new XAttribute(PtOpenXml.HtmlStyle, "list-style-type: upper-alpha;")
+                                    );
+                                }
+                                else if (numFmt == "upperRoman")
+                                {
+                                    listItemHtmlAttributes.Add(
+                                        new XAttribute(PtOpenXml.HtmlStyle, "list-style-type: upper-roman;")
+                                    );
+                                }
+                                else if (numFmt == "custom" && format.StartsWith("0"))
+                                {
+                                    listItemHtmlAttributes.Add(
+                                        new XAttribute(PtOpenXml.HtmlStyle, "list-style-type: decimal-leading-zero;")
+                                    );
+                                }
                             }
                         }
 
@@ -312,8 +377,11 @@ namespace OpenXmlPowerTools
                             .StringConcatenate()
                             .TrimEnd('.');
 
+                        ListItemRetriever.ListItemInfo listItemInfo2 = element.Annotation<ListItemRetriever.ListItemInfo>();
+
                         var listItemRun = new XElement(W.r,
                             new XAttribute(PtOpenXml.ListItemRun, levelNumsString),
+                            listItemInfo2 != null ? new XAttribute(PtOpenXml.AbstractNumId, listItemInfo2.AbstractNumId) : null,
                             element.Attribute(PtOpenXml.FontName),
                             element.Attribute(PtOpenXml.LanguageType),
                             listItemRunProps,
@@ -384,18 +452,178 @@ namespace OpenXmlPowerTools
                         }
                         AddTabAtLeftIndent(element.Element(PtOpenXml.pPr));
 
+                        XElement tabRun = suffix != null ?
+                                new XElement(W.r,
+                                    new XAttribute(PtOpenXml.ListItemRun, levelNumsString),
+                                    listItemRunProps,
+                                    suffix) : null;
+
+                        bool isDeleted = false;
+                        bool isInserted = false;
+                        XAttribute authorAtt = null;
+                        XAttribute dateAtt = null;
+
+                        var paraDelElement = newParaProps
+                            .Elements(W.rPr)
+                            .Elements(W.del)
+                            .FirstOrDefault();
+                        if (paraDelElement != null)
+                        {
+                            isDeleted = true;
+                            authorAtt = paraDelElement.Attribute(W.author);
+                            dateAtt = paraDelElement.Attribute(W.date);
+                        }
+
+                        var paraInsElement = newParaProps
+                            .Elements(W.rPr)
+                            .Elements(W.ins)
+                            .FirstOrDefault();
+                        if (paraInsElement != null)
+                        {
+                            isInserted = true;
+                            authorAtt = paraInsElement.Attribute(W.author);
+                            dateAtt = paraInsElement.Attribute(W.date);
+                        }
+
+                        var paragraphBefore = element
+                            .SiblingsBeforeSelfReverseDocumentOrder()
+                            .FirstOrDefault();
+                        if (paragraphBefore != null)
+                        {
+                            var paraInsElement2 = paragraphBefore
+                                .Elements(W.pPr)
+                                .Elements(W.rPr)
+                                .Elements(W.ins)
+                                .FirstOrDefault();
+                            if (paraInsElement2 != null)
+                            {
+                                isInserted = true;
+                                authorAtt = paraInsElement2.Attribute(W.author);
+                                dateAtt = paraInsElement2.Attribute(W.date);
+                            }
+                        }
+
+#if false
+    <w:p w14:paraId="448CD560"
+         w14:textId="77777777"
+         w:rsidR="003C33D5"
+         w:rsidRDefault="003C33D5"
+         w:rsidP="003C33D5">
+      <w:pPr>
+        <w:pStyle w:val="ListParagraph"/>
+        <w:numPr>
+          <w:ilvl w:val="0"/>
+          <w:numId w:val="1"/>
+        </w:numPr>
+        <w:pPrChange w:id="4"
+                     w:author="e"
+                     w:date="2020-02-07T18:26:00Z">
+          <w:pPr/>
+        </w:pPrChange>
+      </w:pPr>
+      <w:r>
+        <w:t>When you click Online Video, you can paste in the embed code for the video you want to add.</w:t>
+      </w:r>
+    </w:p>
+#endif
+
+                        var pPrChange = element
+                            .Elements(W.pPr)
+                            .Elements(W.pPrChange)
+                            .FirstOrDefault();
+
+                        if (pPrChange != null)
+                        {
+                            authorAtt = pPrChange.Attribute(W.author);
+                            dateAtt = pPrChange.Attribute(W.date);
+
+                            var thisNumPr = element
+                                .Elements(W.pPr)
+                                .Elements(W.numPr)
+                                .FirstOrDefault();
+
+                            var thisNumPrChange = pPrChange
+                                .Elements(W.numPr)
+                                .FirstOrDefault();
+
+                            if (thisNumPr != null && thisNumPrChange == null)
+                                isInserted = true;
+
+                            if (thisNumPr == null && thisNumPrChange != null)
+                                isDeleted = true;
+                        }
+
+                        if (isDeleted)
+                        {
+                            // convert listItemRun and tabRun to their deleted equivalents
+                            var highestId = wDoc
+                                .MainDocumentPart
+                                .GetXDocument()
+                                .Descendants()
+                                .Attributes(W.id)
+                                .Select(id =>
+                                {
+                                    int numId;
+                                    if (int.TryParse((string)id, out numId))
+                                        return numId;
+                                    else
+                                        return 0;
+                                })
+                                .Max();
+
+                            listItemRun = new XElement(W.del,
+                                new XAttribute(W.id, highestId + 1),
+                                authorAtt,
+                                dateAtt,
+                                (XElement)TransformToDeleted(listItemRun));
+                            tabRun = new XElement(W.del,
+                                new XAttribute(W.id, highestId + 2),
+                                authorAtt,
+                                dateAtt,
+                                (XElement)TransformToDeleted(tabRun));
+                        }
+                        else
+                        {
+                            if (isInserted)
+                            {
+                                // convert listItemRun and tabRun to their inserted equivalents
+                                var highestId = wDoc
+                                    .MainDocumentPart
+                                    .GetXDocument()
+                                    .Descendants()
+                                    .Attributes(W.id)
+                                    .Select(id =>
+                                    {
+                                        int numId;
+                                        if (int.TryParse((string)id, out numId))
+                                            return numId;
+                                        else
+                                            return 0;
+                                    })
+                                    .Max();
+
+                                listItemRun = new XElement(W.ins,
+                                    new XAttribute(W.id, highestId + 1),
+                                    authorAtt,
+                                    dateAtt,
+                                    listItemRun);
+                                tabRun = new XElement(W.ins,
+                                    new XAttribute(W.id, highestId + 2),
+                                    authorAtt,
+                                    dateAtt,
+                                    tabRun);
+                            }
+                        }
+
                         XElement newPara = new XElement(W.p,
                             element.Attribute(PtOpenXml.FontName),
                             element.Attribute(PtOpenXml.LanguageType),
                             element.Attribute(PtOpenXml.Unid),
                             new XAttribute(PtOpenXml.AbstractNumId, abstractNumId),
+                            listItemHtmlAttributes,
                             newParaProps,
                             listItemRun,
-                            suffix != null ?
-                                new XElement(W.r,
-                                    new XAttribute(PtOpenXml.ListItemRun, levelNumsString),
-                                    listItemRunProps,
-                                    suffix) : null,
+                            tabRun,
                             element.Elements().Where(e => e.Name != W.pPr).Select(n => NormalizeListItemsTransform(fai, wDoc, n, settings)));
                         return newPara;
 
@@ -409,6 +637,21 @@ namespace OpenXmlPowerTools
             return node;
         }
 
+        private static object TransformToDeleted(XNode node)
+        {
+            XElement element = node as XElement;
+            if (element != null)
+            {
+                if (element.Name == W.t)
+                    return new XElement(W.delText, element.Value);
+
+                return new XElement(element.Name,
+                    element.Attributes(),
+                    element.Nodes().Select(n => TransformToDeleted(n)));
+            }
+            return node;
+        }
+
         private static void AddTabAtLeftIndent(XElement pPr)
         {
             int left = 0;
@@ -423,7 +666,7 @@ namespace OpenXmlPowerTools
                 tabs = new XElement(W.tabs);
                 pPr.Add(tabs);
             }
-            var tabAtLeft = tabs.Elements(W.tab).FirstOrDefault(t => (int)t.Attribute(W.pos) == left);
+            var tabAtLeft = tabs.Elements(W.tab).FirstOrDefault(t => WordprocessingMLUtil.StringToTwips((string)t.Attribute(W.pos)) == left);
             if (tabAtLeft == null)
             {
                 tabs.Add(
@@ -436,6 +679,8 @@ namespace OpenXmlPowerTools
         public static XName[] PtNamesToKeep = new[] {
             PtOpenXml.FontName,
             PtOpenXml.AbstractNumId,
+            PtOpenXml.HtmlStructure,
+            PtOpenXml.HtmlStyle,
             PtOpenXml.StyleName,
             PtOpenXml.LanguageType,
             PtOpenXml.ListItemRun,
@@ -1715,7 +1960,7 @@ namespace OpenXmlPowerTools
             var hps = higherPriorityElement.Elements().Select(e =>
                 new
                 {
-                    Pos = (int)e.Attribute(W.pos),
+                    Pos = WordprocessingMLUtil.StringToTwips((string)e.Attribute(W.pos)),
                     Pri = 1,
                     Element = e,
                 }
@@ -1723,7 +1968,7 @@ namespace OpenXmlPowerTools
             var lps = lowerPriorityElement.Elements().Select(e =>
                 new
                 {
-                    Pos = (int)e.Attribute(W.pos),
+                    Pos = WordprocessingMLUtil.StringToTwips((string)e.Attribute(W.pos)),
                     Pri = 2,
                     Element = e,
                 }
@@ -1732,7 +1977,7 @@ namespace OpenXmlPowerTools
                 .GroupBy(s => s.Pos)
                 .Select(g => g.OrderBy(s => s.Pri).First().Element)
                 .Where(e => (string)e.Attribute(W.val) != "clear")
-                .OrderBy(e => (int)e.Attribute(W.pos));
+                .OrderBy(e => WordprocessingMLUtil.StringToTwips((string)e.Attribute(W.pos)));
             var newTabs = new XElement(W.tabs, newTabElements);
             return newTabs;
         }

+ 2 - 0
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/HtmlToWmlConverterCore.cs

@@ -411,6 +411,8 @@ namespace OpenXmlPowerTools.HtmlToWml
 
         private static Dictionary<XName, int> Order_rPr = new Dictionary<XName, int>
         {
+            { W.moveFrom, 5 },
+            { W.moveTo, 7 },
             { W.ins, 10 },
             { W.del, 20 },
             { W.rStyle, 30 },

+ 20 - 17
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/ListItemRetriever.cs

@@ -17,7 +17,7 @@ namespace OpenXmlPowerTools
             {
                 {"fr-FR", ListItemTextGetter_fr_FR.GetListItemText},
                 {"tr-TR", ListItemTextGetter_tr_TR.GetListItemText},
-                {"ru-RU", ListItemTextGetter_ru_RU.GetListItemText}, 
+                {"ru-RU", ListItemTextGetter_ru_RU.GetListItemText},
                 {"sv-SE", ListItemTextGetter_sv_SE.GetListItemText},
                 {"zh-CN", ListItemTextGetter_zh_CN.GetListItemText},
             };
@@ -136,6 +136,18 @@ namespace OpenXmlPowerTools
 
             public XElement Lvl(int ilvl)
             {
+                var lvl2 = Main.Lvl(ilvl);
+                if (lvl2 == null)
+                {
+                    for (int i = ilvl - 1; i >= 0; i--)
+                    {
+                        lvl2 = Main.Lvl(i);
+                        if (lvl2 != null)
+                            break;
+                    }
+                }
+                if (lvl2 != null)
+                    return lvl2;
                 if (NumStyleLink != null)
                 {
                     var lvl = NumStyleLink.Lvl(ilvl);
@@ -150,17 +162,7 @@ namespace OpenXmlPowerTools
                     }
                     return lvl;
                 }
-                var lvl2 = Main.Lvl(ilvl);
-                if (lvl2 == null)
-                {
-                    for (int i = ilvl - 1; i >= 0; i--)
-                    {
-                        lvl2 = Main.Lvl(i);
-                        if (lvl2 != null)
-                            break;
-                    }
-                }
-                return lvl2;
+                return null;
             }
 
             public int? StartOverride(int ilvl)
@@ -333,7 +335,7 @@ namespace OpenXmlPowerTools
                 IsZeroNumId = isZeroNumId;
             }
         }
-        
+
         public static void SetParagraphLevel(XElement paragraph, int ilvl)
         {
             var pi = paragraph.Annotation<ParagraphInfo>();
@@ -572,7 +574,7 @@ namespace OpenXmlPowerTools
             return listItemSource;
         }
 
-        private static ListItemSource InitializeStyleListItemSource(XDocument numXDoc, XDocument stylesXDoc, XElement paragraph, string paragraphStyleName, 
+        private static ListItemSource InitializeStyleListItemSource(XDocument numXDoc, XDocument stylesXDoc, XElement paragraph, string paragraphStyleName,
             out int? ilvl, out bool? zeroNumId)
         {
             zeroNumId = null;
@@ -759,7 +761,8 @@ namespace OpenXmlPowerTools
             var numXDoc = numberingDefinitionsPart.GetXDocument();
             var stylesXDoc = styleDefinitionsPart.GetXDocument();
 
-            var lvl = listItemInfo.Lvl(GetParagraphLevel(paragraph));
+            var paragraphLevel = GetParagraphLevel(paragraph);
+            var lvl = listItemInfo.Lvl(paragraphLevel);
 
             string lvlText = (string)lvl.Elements(W.lvlText).Attributes(W.val).FirstOrDefault();
             if (lvlText == null)
@@ -771,7 +774,7 @@ namespace OpenXmlPowerTools
 
             int[] levelNumbers = levelNumbersAnnotation.LevelNumbersArray;
             string languageIdentifier = GetLanguageIdentifier(paragraph, stylesXDoc);
-            string listItem = FormatListItem(listItemInfo, levelNumbers, GetParagraphLevel(paragraph), 
+            string listItem = FormatListItem(listItemInfo, levelNumbers, GetParagraphLevel(paragraph),
                 lvlText, stylesXDoc, languageIdentifier, settings);
             return listItem;
         }
@@ -872,7 +875,7 @@ namespace OpenXmlPowerTools
         private static void InitializeListItemRetrieverForPart(WordprocessingDocument wordDoc, OpenXmlPart part, ListItemRetrieverSettings settings)
         {
             var mainXDoc = part.GetXDocument();
-            
+
             var numPart = wordDoc.MainDocumentPart.NumberingDefinitionsPart;
             if (numPart == null)
                 return;

+ 273 - 211
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/MarkupSimplifier.cs

@@ -3,7 +3,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Xml.Linq;
 using System.Xml.Schema;
@@ -41,7 +40,6 @@ namespace OpenXmlPowerTools
         public bool ReplaceTabsWithSpaces;
     }
 
-    [SuppressMessage("ReSharper", "InconsistentNaming")]
     public static class MarkupSimplifier
     {
         public static WmlDocument SimplifyMarkup(WmlDocument doc, SimplifyMarkupSettings settings)
@@ -49,7 +47,10 @@ namespace OpenXmlPowerTools
             using (var streamDoc = new OpenXmlMemoryStreamDocument(doc))
             {
                 using (WordprocessingDocument document = streamDoc.GetWordprocessingDocument())
+                {
                     SimplifyMarkup(document, settings);
+                }
+
                 return streamDoc.GetModifiedWmlDocument();
             }
         }
@@ -61,17 +62,31 @@ namespace OpenXmlPowerTools
                 settings.RemoveRsidInfo = true;
                 RemoveElementsForDocumentComparison(doc);
             }
+
             if (settings.RemoveRsidInfo)
+            {
                 RemoveRsidInfoInSettings(doc);
+            }
+
             if (settings.AcceptRevisions)
+            {
                 RevisionAccepter.AcceptRevisions(doc);
+            }
+
             foreach (OpenXmlPart part in doc.ContentParts())
+            {
                 SimplifyMarkupForPart(part, settings);
+            }
 
             if (doc.MainDocumentPart.StyleDefinitionsPart != null)
+            {
                 SimplifyMarkupForPart(doc.MainDocumentPart.StyleDefinitionsPart, settings);
+            }
+
             if (doc.MainDocumentPart.StylesWithEffectsPart != null)
+            {
                 SimplifyMarkupForPart(doc.MainDocumentPart.StylesWithEffectsPart, settings);
+            }
 
             if (settings.RemoveComments)
             {
@@ -116,13 +131,15 @@ namespace OpenXmlPowerTools
             XDocument mainXDoc = doc.MainDocumentPart.GetXDocument();
             List<XElement> bookmarkStart = mainXDoc
                 .Descendants(W.bookmarkStart)
-                .Where(b => (string) b.Attribute(W.name) == "_GoBack")
+                .Where(b => (string)b.Attribute(W.name) == "_GoBack")
                 .ToList();
+
             foreach (XElement item in bookmarkStart)
             {
                 IEnumerable<XElement> bookmarkEnd = mainXDoc
                     .Descendants(W.bookmarkEnd)
-                    .Where(be => (int) be.Attribute(W.id) == (int) item.Attribute(W.id));
+                    .Where(be => (int)be.Attribute(W.id) == (int)item.Attribute(W.id));
+
                 bookmarkEnd.Remove();
             }
 
@@ -130,60 +147,70 @@ namespace OpenXmlPowerTools
             doc.MainDocumentPart.PutXDocument();
         }
 
+
         public static XElement MergeAdjacentSuperfluousRuns(XElement element)
         {
-            return (XElement) MergeAdjacentRunsTransform(element);
+            return (XElement)MergeAdjacentRunsTransform(element);
         }
 
         public static XElement TransformElementToSingleCharacterRuns(XElement element)
         {
-            return (XElement) SingleCharacterRunTransform(element);
+            return (XElement)SingleCharacterRunTransform(element);
         }
 
         public static void TransformPartToSingleCharacterRuns(OpenXmlPart part)
         {
             // After transforming to single character runs, Rsid info will be invalid, so
             // remove from the part.
-            XDocument xDoc = part.GetXDocument();
-            var newRoot = (XElement) RemoveRsidTransform(xDoc.Root);
-            newRoot = (XElement) SingleCharacterRunTransform(newRoot);
-            xDoc.Elements().First().ReplaceWith(newRoot);
-            part.PutXDocument();
+            XElement root = part.GetXElement();
+            var newRoot = (XElement)RemoveRsidTransform(root);
+            newRoot = (XElement)SingleCharacterRunTransform(newRoot);
+            root.ReplaceWith(newRoot);
+            part.PutXElement();
         }
 
         public static void TransformToSingleCharacterRuns(WordprocessingDocument doc)
         {
             if (RevisionAccepter.HasTrackedRevisions(doc))
+            {
                 throw new OpenXmlPowerToolsException(
                     "Transforming a document to single character runs is not supported for " +
                     "a document with tracked revisions.");
+            }
 
             foreach (OpenXmlPart part in doc.ContentParts())
+            {
                 TransformPartToSingleCharacterRuns(part);
+            }
         }
 
         private static object RemoveCustomXmlAndContentControlsTransform(
-            XNode node, SimplifyMarkupSettings simplifyMarkupSettings)
+            XNode node, 
+            SimplifyMarkupSettings simplifyMarkupSettings)
         {
-            XElement element = node as XElement;
-            if (element != null)
+
+            if (node is XElement element)
             {
                 if (simplifyMarkupSettings.RemoveSmartTags &&
                     element.Name == W.smartTag)
+                {
                     return element
                         .Elements()
                         .Select(e =>
                             RemoveCustomXmlAndContentControlsTransform(e,
                                 simplifyMarkupSettings));
+                }
 
                 if (simplifyMarkupSettings.RemoveContentControls &&
                     element.Name == W.sdt)
+                {
                     return element
                         .Elements(W.sdtContent)
                         .Elements()
                         .Select(e =>
                             RemoveCustomXmlAndContentControlsTransform(e,
                                 simplifyMarkupSettings));
+                }
 
                 return new XElement(element.Name,
                     element.Attributes(),
@@ -195,52 +222,50 @@ namespace OpenXmlPowerTools
 
         private static object RemoveRsidTransform(XNode node)
         {
-            var element = node as XElement;
-            if (element == null) return node;
-
-            if (element.Name == W.rsid)
-                return null;
+            if (node is XElement element)
+            {
+                return element.Name == W.rsid
+                    ? null
+                    : new XElement(element.Name,
+                        element
+                            .Attributes()
+                            .Where(a => a.Name != W.rsid &&
+                                        a.Name != W.rsidDel &&
+                                        a.Name != W.rsidP &&
+                                        a.Name != W.rsidR &&
+                                        a.Name != W.rsidRDefault &&
+                                        a.Name != W.rsidRPr &&
+                                        a.Name != W.rsidSect &&
+                                        a.Name != W.rsidTr),
+                        element.Nodes().Select(RemoveRsidTransform));
+            }
 
-            return new XElement(element.Name,
-                element
-                    .Attributes()
-                    .Where(a => (a.Name != W.rsid) &&
-                                (a.Name != W.rsidDel) &&
-                                (a.Name != W.rsidP) &&
-                                (a.Name != W.rsidR) &&
-                                (a.Name != W.rsidRDefault) &&
-                                (a.Name != W.rsidRPr) &&
-                                (a.Name != W.rsidSect) &&
-                                (a.Name != W.rsidTr)),
-                element.Nodes().Select(n => RemoveRsidTransform(n)));
+            return node;
         }
 
         private static object MergeAdjacentRunsTransform(XNode node)
         {
-            var element = node as XElement;
-            if (element == null) return node;
-
-            if (element.Name == W.p)
-                return WordprocessingMLUtil.CoalesceAdjacentRunsWithIdenticalFormatting(element);
+            if (node is XElement element)
+            {
+                return element.Name == W.p
+                    ? WordprocessingMLUtil.CoalesceAdjacentRunsWithIdenticalFormatting(element)
+                    : new XElement(element.Name,
+                        element.Attributes(),
+                        element.Nodes().Select(MergeAdjacentRunsTransform));
+            }
 
-            return new XElement(element.Name,
-                element.Attributes(),
-                element.Nodes().Select(n => MergeAdjacentRunsTransform(n)));
+            return node;
         }
 
-        private static object RemoveEmptyRunsAndRunPropertiesTransform(
-            XNode node)
+        private static object RemoveEmptyRunsAndRunPropertiesTransform(XNode node)
         {
-            var element = node as XElement;
-            if (element != null)
+            if (node is XElement element)
             {
-                if (((element.Name == W.r) || (element.Name == W.rPr) || (element.Name == W.pPr)) &&
-                    !element.Elements().Any())
-                    return null;
-
-                return new XElement(element.Name,
-                    element.Attributes(),
-                    element.Nodes().Select(n => RemoveEmptyRunsAndRunPropertiesTransform(n)));
+                return (element.Name == W.r || element.Name == W.rPr || element.Name == W.pPr) && !element.Elements().Any()
+                    ? null
+                    : new XElement(element.Name,
+                        element.Attributes(),
+                        element.Nodes().Select(RemoveEmptyRunsAndRunPropertiesTransform));
             }
 
             return node;
@@ -249,37 +274,40 @@ namespace OpenXmlPowerTools
         private static object MergeAdjacentInstrText(
             XNode node)
         {
-            var element = node as XElement;
-            if (element != null)
+            if (node is XElement element)
             {
-                if ((element.Name == W.r) && element.Elements(W.instrText).Any())
+                if (element.Name == W.r && element.Elements(W.instrText).Any())
                 {
-                    IEnumerable<IGrouping<bool, XElement>> grouped =
-                        element.Elements().GroupAdjacent(e => e.Name == W.instrText);
+                    IEnumerable<IGrouping<bool, XElement>> grouped = element
+                        .Elements()
+                        .GroupAdjacent(e => e.Name == W.instrText);
+
                     return new XElement(W.r,
                         grouped.Select(g =>
                         {
                             if (g.Key == false)
-                                return (object) g;
+                            {
+                                return (object)g;
+                            }
 
                             // If .doc files are converted to .docx by the Binary to Open XML Translator,
                             // the w:instrText elements might be empty, in which case newInstrText would
                             // be an empty string.
-                            string newInstrText = g.Select(i => (string) i).StringConcatenate();
+                            string newInstrText = g.Select(i => (string)i).StringConcatenate();
                             if (string.IsNullOrEmpty(newInstrText))
+                            {
                                 return new XElement(W.instrText);
+                            }
 
                             return new XElement(W.instrText,
-                                (newInstrText[0] == ' ') || (newInstrText[newInstrText.Length - 1] == ' ')
-                                    ? new XAttribute(XNamespace.Xml + "space", "preserve")
-                                    : null,
+                                XmlUtil.GetXmlSpaceAttribute(newInstrText),
                                 newInstrText);
                         }));
                 }
 
                 return new XElement(element.Name,
                     element.Attributes(),
-                    element.Nodes().Select(n => MergeAdjacentInstrText(n)));
+                    element.Nodes().Select(MergeAdjacentInstrText));
             }
 
             return node;
@@ -299,77 +327,103 @@ namespace OpenXmlPowerTools
             SimplifyMarkupSettings settings,
             SimplifyMarkupParameters parameters)
         {
-            var element = node as XElement;
-            if (element == null) return node;
+            if (!(node is XElement element)) return node;
 
             if (settings.RemovePermissions &&
-                ((element.Name == W.permEnd) ||
-                 (element.Name == W.permStart)))
+                (element.Name == W.permEnd ||
+                 element.Name == W.permStart))
+            {
                 return null;
+            }
 
             if (settings.RemoveProof &&
-                ((element.Name == W.proofErr) ||
-                 (element.Name == W.noProof)))
+                (element.Name == W.proofErr ||
+                 element.Name == W.noProof))
+            {
                 return null;
+            }
 
             if (settings.RemoveSoftHyphens &&
-                (element.Name == W.softHyphen))
+                element.Name == W.softHyphen)
+            {
                 return null;
+            }
 
             if (settings.RemoveLastRenderedPageBreak &&
-                (element.Name == W.lastRenderedPageBreak))
+                element.Name == W.lastRenderedPageBreak)
+            {
                 return null;
+            }
 
             if (settings.RemoveBookmarks &&
-                ((element.Name == W.bookmarkStart) ||
-                 (element.Name == W.bookmarkEnd)))
+                (element.Name == W.bookmarkStart ||
+                 element.Name == W.bookmarkEnd))
+            {
                 return null;
+            }
 
             if (settings.RemoveGoBackBookmark &&
-                (((element.Name == W.bookmarkStart) && ((int) element.Attribute(W.id) == parameters.GoBackId)) ||
-                 ((element.Name == W.bookmarkEnd) && ((int) element.Attribute(W.id) == parameters.GoBackId))))
+                (element.Name == W.bookmarkStart && (int)element.Attribute(W.id) == parameters.GoBackId ||
+                 element.Name == W.bookmarkEnd && (int)element.Attribute(W.id) == parameters.GoBackId))
+            {
                 return null;
+            }
 
             if (settings.RemoveWebHidden &&
-                (element.Name == W.webHidden))
+                element.Name == W.webHidden)
+            {
                 return null;
+            }
 
             if (settings.ReplaceTabsWithSpaces &&
-                (element.Name == W.tab) && 
-                (element.Parent != null && element.Parent.Name == W.r))
+                element.Name == W.tab && element.Parent != null && element.Parent.Name == W.r)
+            {
                 return new XElement(W.t, new XAttribute(XNamespace.Xml + "space", "preserve"), " ");
+            }
 
             if (settings.RemoveComments &&
-                ((element.Name == W.commentRangeStart) ||
-                 (element.Name == W.commentRangeEnd) ||
-                 (element.Name == W.commentReference) ||
-                 (element.Name == W.annotationRef)))
+                (element.Name == W.commentRangeStart ||
+                 element.Name == W.commentRangeEnd ||
+                 element.Name == W.commentReference ||
+                 element.Name == W.annotationRef))
+            {
                 return null;
+            }
 
             if (settings.RemoveComments &&
-                (element.Name == W.rStyle) &&
-                (element.Attribute(W.val).Value == "CommentReference"))
+                element.Name == W.rStyle &&
+                element.Attribute(W.val)?.Value == "CommentReference")
+            {
                 return null;
+            }
 
             if (settings.RemoveEndAndFootNotes &&
-                ((element.Name == W.endnoteReference) ||
-                 (element.Name == W.footnoteReference)))
+                (element.Name == W.endnoteReference ||
+                 element.Name == W.footnoteReference))
+            {
                 return null;
+            }
 
             if (settings.RemoveFieldCodes)
             {
                 if (element.Name == W.fldSimple)
+                {
                     return element.Elements().Select(e => SimplifyMarkupTransform(e, settings, parameters));
+                }
 
-                if ((element.Name == W.fldData) ||
-                    (element.Name == W.fldChar) ||
-                    (element.Name == W.instrText))
+                if (element.Name == W.fldData ||
+                    element.Name == W.fldChar ||
+                    element.Name == W.instrText)
+                {
                     return null;
+                }
             }
 
             if (settings.RemoveHyperlinks &&
-                (element.Name == W.hyperlink))
+                element.Name == W.hyperlink)
+            {
                 return element.Elements();
+            }
 
             return new XElement(element.Name,
                 element.Attributes(),
@@ -378,6 +432,7 @@ namespace OpenXmlPowerTools
 
         private static XDocument Normalize(XDocument source, XmlSchemaSet schema)
         {
+
             var havePsvi = false;
 
             // validate, throw errors, add PSVI information
@@ -386,19 +441,18 @@ namespace OpenXmlPowerTools
                 source.Validate(schema, null, true);
                 havePsvi = true;
             }
+
+            // Remove comments, processing instructions, and text nodes that are
+            // children of XDocument. Only white space text nodes are allowed as
+            // children of a document, so we can remove all text nodes.
             return new XDocument(
                 source.Declaration,
                 source.Nodes().Select(n =>
-                {
-                    // Remove comments, processing instructions, and text nodes that are
-                    // children of XDocument.  Only white space text nodes are allowed as
-                    // children of a document, so we can remove all text nodes.
-                    if (n is XComment || n is XProcessingInstruction || n is XText)
-                        return null;
-
-                    var e = n as XElement;
-                    return e != null ? NormalizeElement(e, havePsvi) : n;
-                }));
+                    n is XComment || n is XProcessingInstruction || n is XText
+                        ? null
+                        : n is XElement e
+                            ? NormalizeElement(e, havePsvi)
+                            : n));
         }
 
         // TODO: Check whether this can be removed.
@@ -411,52 +465,55 @@ namespace OpenXmlPowerTools
 
         private static IEnumerable<XAttribute> NormalizeAttributes(XElement element, bool havePsvi)
         {
-            return element.Attributes()
-                .Where(a => !a.IsNamespaceDeclaration &&
-                            (a.Name != Xsi.schemaLocation) &&
-                            (a.Name != Xsi.noNamespaceSchemaLocation))
-                .OrderBy(a => a.Name.NamespaceName)
-                .ThenBy(a => a.Name.LocalName)
-                .Select(a =>
-                {
-                    if (havePsvi)
-                    {
-                        IXmlSchemaInfo schemaInfo = a.GetSchemaInfo();
-                        XmlSchemaType schemaType = schemaInfo != null ? schemaInfo.SchemaType : null;
-                        XmlTypeCode? typeCode = schemaType != null ? schemaType.TypeCode : (XmlTypeCode?) null;
-
-                        switch (typeCode)
-                        {
-                            case XmlTypeCode.Boolean:
-                                return new XAttribute(a.Name, (bool) a);
-                            case XmlTypeCode.DateTime:
-                                return new XAttribute(a.Name, (DateTime) a);
-                            case XmlTypeCode.Decimal:
-                                return new XAttribute(a.Name, (decimal) a);
-                            case XmlTypeCode.Double:
-                                return new XAttribute(a.Name, (double) a);
-                            case XmlTypeCode.Float:
-                                return new XAttribute(a.Name, (float) a);
-                            case XmlTypeCode.HexBinary:
-                            case XmlTypeCode.Language:
-                                return new XAttribute(a.Name,
-                                    ((string) a).ToLower());
-                        }
-                    }
-
-                    return a;
-                });
+            return element
+                 .Attributes()
+                 .Where(a => !a.IsNamespaceDeclaration &&
+                             a.Name != XSI.schemaLocation &&
+                             a.Name != XSI.noNamespaceSchemaLocation)
+                 .OrderBy(a => a.Name.NamespaceName)
+                 .ThenBy(a => a.Name.LocalName)
+                 .Select(a =>
+                 {
+                     if (havePsvi)
+                     {
+                         IXmlSchemaInfo schemaInfo = a.GetSchemaInfo();
+                         XmlSchemaType schemaType = schemaInfo?.SchemaType;
+                         XmlTypeCode? typeCode = schemaType?.TypeCode;
+
+                         switch (typeCode)
+                         {
+                             case XmlTypeCode.Boolean:
+                                 return new XAttribute(a.Name, (bool)a);
+                             case XmlTypeCode.DateTime:
+                                 return new XAttribute(a.Name, (DateTime)a);
+                             case XmlTypeCode.Decimal:
+                                 return new XAttribute(a.Name, (decimal)a);
+                             case XmlTypeCode.Double:
+                                 return new XAttribute(a.Name, (double)a);
+                             case XmlTypeCode.Float:
+                                 return new XAttribute(a.Name, (float)a);
+                             case XmlTypeCode.HexBinary:
+                             case XmlTypeCode.Language:
+                                 return new XAttribute(a.Name, ((string)a).ToLower());
+                         }
+                     }
+
+                     return a;
+                 });
         }
 
         private static XNode NormalizeNode(XNode node, bool havePsvi)
         {
             // trim comments and processing instructions from normalized tree
             if (node is XComment || node is XProcessingInstruction)
+            {
                 return null;
+            }
 
-            var e = node as XElement;
-            if (e != null)
+            if (node is XElement e)
+            {
                 return NormalizeElement(e, havePsvi);
+            }
 
             // Only thing left is XCData and XText, so clone them
             return node;
@@ -467,36 +524,42 @@ namespace OpenXmlPowerTools
             if (havePsvi)
             {
                 IXmlSchemaInfo schemaInfo = element.GetSchemaInfo();
-                XmlSchemaType schemaType = schemaInfo != null ? schemaInfo.SchemaType : null;
-                XmlTypeCode? typeCode = schemaType != null ? schemaType.TypeCode : (XmlTypeCode?) null;
+                XmlSchemaType schemaType = schemaInfo?.SchemaType;
+                XmlTypeCode? typeCode = schemaType?.TypeCode;
 
                 switch (typeCode)
                 {
                     case XmlTypeCode.Boolean:
                         return new XElement(element.Name,
                             NormalizeAttributes(element, true),
-                            (bool) element);
+                            (bool)element);
+
                     case XmlTypeCode.DateTime:
                         return new XElement(element.Name,
                             NormalizeAttributes(element, true),
-                            (DateTime) element);
+                            (DateTime)element);
+
                     case XmlTypeCode.Decimal:
                         return new XElement(element.Name,
                             NormalizeAttributes(element, true),
-                            (decimal) element);
+                            (decimal)element);
+
                     case XmlTypeCode.Double:
                         return new XElement(element.Name,
                             NormalizeAttributes(element, true),
-                            (double) element);
+                            (double)element);
+
                     case XmlTypeCode.Float:
                         return new XElement(element.Name,
                             NormalizeAttributes(element, true),
-                            (float) element);
+                            (float)element);
+
                     case XmlTypeCode.HexBinary:
                     case XmlTypeCode.Language:
                         return new XElement(element.Name,
                             NormalizeAttributes(element, true),
-                            ((string) element).ToLower());
+                            ((string)element).ToLower());
+
                     default:
                         return new XElement(element.Name,
                             NormalizeAttributes(element, true),
@@ -514,16 +577,19 @@ namespace OpenXmlPowerTools
             var parameters = new SimplifyMarkupParameters();
             if (part.ContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")
             {
-                var doc = (WordprocessingDocument) part.OpenXmlPackage;
+                var doc = (WordprocessingDocument)part.OpenXmlPackage;
                 if (settings.RemoveGoBackBookmark)
                 {
                     XElement goBackBookmark = doc
                         .MainDocumentPart
                         .GetXDocument()
                         .Descendants(W.bookmarkStart)
-                        .FirstOrDefault(bm => (string) bm.Attribute(W.name) == "_GoBack");
+                        .FirstOrDefault(bm => (string)bm.Attribute(W.name) == "_GoBack");
+
                     if (goBackBookmark != null)
-                        parameters.GoBackId = (int) goBackBookmark.Attribute(W.id);
+                    {
+                        parameters.GoBackId = (int)goBackBookmark.Attribute(W.id);
+                    }
                 }
             }
 
@@ -532,11 +598,15 @@ namespace OpenXmlPowerTools
 
             // Need to do this first to enable simplifying hyperlinks.
             if (settings.RemoveContentControls || settings.RemoveSmartTags)
-                newRoot = (XElement) RemoveCustomXmlAndContentControlsTransform(newRoot, settings);
+            {
+                newRoot = (XElement)RemoveCustomXmlAndContentControlsTransform(newRoot, settings);
+            }
 
             // This may touch many elements, so needs to be its own transform.
             if (settings.RemoveRsidInfo)
-                newRoot = (XElement) RemoveRsidTransform(newRoot);
+            {
+                newRoot = (XElement)RemoveRsidTransform(newRoot);
+            }
 
             var prevNewRoot = new XDocument(newRoot);
             while (true)
@@ -551,22 +621,26 @@ namespace OpenXmlPowerTools
                     settings.RemoveWebHidden ||
                     settings.RemoveGoBackBookmark ||
                     settings.RemoveHyperlinks)
-                    newRoot = (XElement) SimplifyMarkupTransform(newRoot, settings, parameters);
+                {
+                    newRoot = (XElement)SimplifyMarkupTransform(newRoot, settings, parameters);
+                }
 
                 // Remove runs and run properties that have become empty due to previous transforms.
-                newRoot = (XElement) RemoveEmptyRunsAndRunPropertiesTransform(newRoot);
+                newRoot = (XElement)RemoveEmptyRunsAndRunPropertiesTransform(newRoot);
 
                 // Merge adjacent runs that have identical run properties.
-                newRoot = (XElement) MergeAdjacentRunsTransform(newRoot);
+                newRoot = (XElement)MergeAdjacentRunsTransform(newRoot);
 
                 // Merge adjacent instrText elements.
-                newRoot = (XElement) MergeAdjacentInstrText(newRoot);
+                newRoot = (XElement)MergeAdjacentInstrText(newRoot);
 
                 // Separate run children into separate runs
-                newRoot = (XElement) SeparateRunChildrenIntoSeparateRuns(newRoot);
+                newRoot = (XElement)SeparateRunChildrenIntoSeparateRuns(newRoot);
 
                 if (XNode.DeepEquals(prevNewRoot.Root, newRoot))
+                {
                     break;
+                }
 
                 prevNewRoot = new XDocument(newRoot);
             }
@@ -592,15 +666,21 @@ namespace OpenXmlPowerTools
                     new XAttribute(XNamespace.Xmlns + "wpi", WPI.wpi),
                     new XAttribute(XNamespace.Xmlns + "wne", WNE.wne),
                     new XAttribute(XNamespace.Xmlns + "wps", WPS.wps),
-                    new XAttribute(MC.Ignorable, "w14 wp14 w15 w16se"),
+                    new XAttribute(MC.Ignorable, "w14 wp14 w15 w16se")
                 };
 
                 XDocument newXDoc = Normalize(new XDocument(newRoot), null);
                 newRoot = newXDoc.Root;
                 if (newRoot != null)
+                {
                     foreach (XAttribute nsAttr in nsAttrs)
+                    {
                         if (newRoot.Attribute(nsAttr.Name) == null)
+                        {
                             newRoot.Add(nsAttr);
+                        }
+                    }
+                }
 
                 part.PutXDocument(newXDoc);
             }
@@ -612,76 +692,58 @@ namespace OpenXmlPowerTools
 
         private static object SeparateRunChildrenIntoSeparateRuns(XNode node)
         {
-            var element = node as XElement;
-            if (element == null) return node;
-
-            if (element.Name == W.r)
+            if (node is XElement element)
             {
-                IEnumerable<XElement> runChildren = element.Elements().Where(e => e.Name != W.rPr);
-                XElement rPr = element.Element(W.rPr);
-                return runChildren.Select(rc => new XElement(W.r, rPr, rc));
+                if (element.Name == W.r)
+                {
+                    IEnumerable<XElement> runChildren = element.Elements().Where(e => e.Name != W.rPr);
+                    XElement rPr = element.Element(W.rPr);
+                    return runChildren.Select(rc => new XElement(W.r, rPr, rc));
+                }
+
+                return new XElement(element.Name,
+                    element.Attributes(),
+                    element.Nodes().Select(SeparateRunChildrenIntoSeparateRuns));
             }
 
-            return new XElement(element.Name,
-                element.Attributes(),
-                element.Nodes().Select(n => SeparateRunChildrenIntoSeparateRuns(n)));
+            return node;
         }
 
         private static object SingleCharacterRunTransform(XNode node)
         {
-            var element = node as XElement;
-            if (element == null) return node;
-
-            if (element.Name == W.r)
-                return element.Elements()
-                    .Where(e => e.Name != W.rPr)
-                    .GroupAdjacent(sr => sr.Name == W.t)
-                    .Select(g =>
-                    {
-                        if (g.Key)
+            if (node is XElement element)
+            {
+                if (element.Name == W.r)
+                    return element.Elements()
+                        .Where(e => e.Name != W.rPr)
+                        .GroupAdjacent(sr => sr.Name == W.t)
+                        .Select(g =>
                         {
-                            string s = g.Select(t => (string) t).StringConcatenate();
-                            return s.Select(c =>
+                            if (g.Key)
+                            {
+                                string s = g.Select(t => (string)t).StringConcatenate();
+                                return s.Select(c =>
+                                    new XElement(W.r,
+                                        element.Elements(W.rPr),
+                                        new XElement(W.t,
+                                            XmlUtil.GetXmlSpaceAttribute(c),
+                                            c)));
+                            }
+
+                            return g.Select(sr =>
                                 new XElement(W.r,
                                     element.Elements(W.rPr),
-                                    new XElement(W.t,
-                                        c == ' ' ? new XAttribute(XNamespace.Xml + "space", "preserve") : null,
-                                        c)));
-                        }
+                                    new XElement(sr.Name,
+                                        sr.Attributes(),
+                                        sr.Nodes().Select(SingleCharacterRunTransform))));
+                        });
 
-                        return g.Select(sr =>
-                            new XElement(W.r,
-                                element.Elements(W.rPr),
-                                new XElement(sr.Name,
-                                    sr.Attributes(),
-                                    sr.Nodes().Select(n => SingleCharacterRunTransform(n)))));
-                    });
-
-            return new XElement(element.Name,
-                element.Attributes(),
-                element.Nodes().Select(n => SingleCharacterRunTransform(n)));
-        }
-
-        private static class Xsi
-        {
-            private static readonly XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
-
-            public static readonly XName schemaLocation = xsi + "schemaLocation";
-            public static readonly XName noNamespaceSchemaLocation = xsi + "noNamespaceSchemaLocation";
-        }
-
-        public class InternalException : Exception
-        {
-            public InternalException(string message) : base(message)
-            {
+                return new XElement(element.Name,
+                    element.Attributes(),
+                    element.Nodes().Select(SingleCharacterRunTransform));
             }
-        }
 
-        public class InvalidSettingsException : Exception
-        {
-            public InvalidSettingsException(string message) : base(message)
-            {
-            }
+            return node;
         }
 
         private class SimplifyMarkupParameters

+ 2 - 2
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/MetricsGetter.cs

@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Drawing;
 using System.IO;
 using System.IO.Packaging;
 using System.Linq;
@@ -11,7 +12,6 @@ using System.Xml.Linq;
 using DocumentFormat.OpenXml.Packaging;
 using DocumentFormat.OpenXml.Validation;
 using System.Globalization;
-using System.Drawing;
 
 namespace OpenXmlPowerTools
 {
@@ -821,7 +821,7 @@ namespace OpenXmlPowerTools
             {
                 var styleChain = item.Split('/');
                 XElement elementToAddTo = styleHierarchy;
-                foreach (var inChain in styleChain.SkipLast(1))
+                foreach (var inChain in styleChain.PtSkipLast(1))
                     elementToAddTo = elementToAddTo.Elements(H.Style).FirstOrDefault(z => z.Attribute(H.Id).Value == inChain);
                 var styleToAdd = styleChain.Last();
                 elementToAddTo.Add(

+ 1 - 1
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PresentationBuilder.cs

@@ -635,7 +635,7 @@ namespace OpenXmlPowerTools
             IEnumerable<XElement> newContent, List<ImageData> images, List<MediaData> mediaList)
         {
             var relevantElements = newContent.DescendantsAndSelf()
-                .Where(d => d.Name == VML.imagedata || d.Name == VML.fill || d.Name == VML.stroke || d.Name == A.blip)
+                .Where(d => d.Name == VML.imagedata || d.Name == VML.fill || d.Name == VML.stroke || d.Name == A.blip || d.Name == SVG.svgBlip)
                 .ToList();
             foreach (XElement imageReference in relevantElements)
             {

+ 226 - 162
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PtOpenXmlDocument.cs

@@ -47,32 +47,127 @@ Here is creating a new WmlDocument:
 */
 
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
+using System.IO.Packaging;
 using System.Linq;
 using System.Xml.Linq;
-using System.IO.Packaging;
+using DocumentFormat.OpenXml;
 using DocumentFormat.OpenXml.Packaging;
 
 namespace OpenXmlPowerTools
 {
     public class PowerToolsDocumentException : Exception
     {
-        public PowerToolsDocumentException(string message) : base(message) { }
+        public PowerToolsDocumentException(string message) : base(message)
+        {
+        }
     }
+
     public class PowerToolsInvalidDataException : Exception
     {
-        public PowerToolsInvalidDataException(string message) : base(message) { }
+        public PowerToolsInvalidDataException(string message) : base(message)
+        {
+        }
     }
 
+    [SuppressMessage("ReSharper", "MemberCanBeProtected.Global")]
     public class OpenXmlPowerToolsDocument
     {
+        public OpenXmlPowerToolsDocument(OpenXmlPowerToolsDocument original)
+        {
+            DocumentByteArray = new byte[original.DocumentByteArray.Length];
+            Array.Copy(original.DocumentByteArray, DocumentByteArray, original.DocumentByteArray.Length);
+            FileName = original.FileName;
+        }
+
+        public OpenXmlPowerToolsDocument(OpenXmlPowerToolsDocument original, bool convertToTransitional)
+        {
+            if (convertToTransitional)
+            {
+                ConvertToTransitional(original.FileName, original.DocumentByteArray);
+            }
+            else
+            {
+                DocumentByteArray = new byte[original.DocumentByteArray.Length];
+                Array.Copy(original.DocumentByteArray, DocumentByteArray, original.DocumentByteArray.Length);
+                FileName = original.FileName;
+            }
+        }
+
+        public OpenXmlPowerToolsDocument(string fileName)
+        {
+            FileName = fileName;
+            DocumentByteArray = File.ReadAllBytes(fileName);
+        }
+
+        public OpenXmlPowerToolsDocument(string fileName, bool convertToTransitional)
+        {
+            FileName = fileName;
+
+            if (convertToTransitional)
+            {
+                byte[] tempByteArray = File.ReadAllBytes(fileName);
+                ConvertToTransitional(fileName, tempByteArray);
+            }
+            else
+            {
+                FileName = fileName;
+                DocumentByteArray = File.ReadAllBytes(fileName);
+            }
+        }
+
+        public OpenXmlPowerToolsDocument(byte[] byteArray)
+        {
+            DocumentByteArray = new byte[byteArray.Length];
+            Array.Copy(byteArray, DocumentByteArray, byteArray.Length);
+            FileName = null;
+        }
+
+        public OpenXmlPowerToolsDocument(byte[] byteArray, bool convertToTransitional)
+        {
+            if (convertToTransitional)
+            {
+                ConvertToTransitional(null, byteArray);
+            }
+            else
+            {
+                DocumentByteArray = new byte[byteArray.Length];
+                Array.Copy(byteArray, DocumentByteArray, byteArray.Length);
+                FileName = null;
+            }
+        }
+
+        public OpenXmlPowerToolsDocument(string fileName, MemoryStream memStream)
+        {
+            FileName = fileName;
+            DocumentByteArray = new byte[memStream.Length];
+            Array.Copy(memStream.GetBuffer(), DocumentByteArray, memStream.Length);
+        }
+
+        public OpenXmlPowerToolsDocument(string fileName, MemoryStream memStream, bool convertToTransitional)
+        {
+            if (convertToTransitional)
+            {
+                ConvertToTransitional(fileName, memStream.ToArray());
+            }
+            else
+            {
+                FileName = fileName;
+                DocumentByteArray = new byte[memStream.Length];
+                Array.Copy(memStream.GetBuffer(), DocumentByteArray, memStream.Length);
+            }
+        }
+
         public string FileName { get; set; }
+
         public byte[] DocumentByteArray { get; set; }
 
         public static OpenXmlPowerToolsDocument FromFileName(string fileName)
         {
             byte[] bytes = File.ReadAllBytes(fileName);
             Type type;
+
             try
             {
                 type = GetDocumentType(bytes);
@@ -81,18 +176,27 @@ namespace OpenXmlPowerTools
             {
                 throw new PowerToolsDocumentException("Not an Open XML document.");
             }
+
             if (type == typeof(WordprocessingDocument))
+            {
                 return new WmlDocument(fileName, bytes);
+            }
+
             if (type == typeof(SpreadsheetDocument))
+            {
                 return new SmlDocument(fileName, bytes);
+            }
+
             if (type == typeof(PresentationDocument))
+            {
                 return new PmlDocument(fileName, bytes);
+            }
+
             if (type == typeof(Package))
             {
-                OpenXmlPowerToolsDocument pkg = new OpenXmlPowerToolsDocument(bytes);
-                pkg.FileName = fileName;
-                return pkg;
+                return new OpenXmlPowerToolsDocument(bytes) { FileName = fileName };
             }
+
             throw new PowerToolsDocumentException("Not an Open XML document.");
         }
 
@@ -100,55 +204,21 @@ namespace OpenXmlPowerTools
         {
             Type type = doc.GetDocumentType();
             if (type == typeof(WordprocessingDocument))
-                return new WmlDocument(doc);
-            if (type == typeof(SpreadsheetDocument))
-                return new SmlDocument(doc);
-            if (type == typeof(PresentationDocument))
-                return new PmlDocument(doc);
-            return null;    // This should not be possible from a valid OpenXmlPowerToolsDocument object
-        }
-
-        public OpenXmlPowerToolsDocument(OpenXmlPowerToolsDocument original)
-        {
-            DocumentByteArray = new byte[original.DocumentByteArray.Length];
-            Array.Copy(original.DocumentByteArray, DocumentByteArray, original.DocumentByteArray.Length);
-            FileName = original.FileName;
-        }
-
-        public OpenXmlPowerToolsDocument(OpenXmlPowerToolsDocument original, bool convertToTransitional)
-        {
-            if (convertToTransitional)
-            {
-                ConvertToTransitional(original.FileName, original.DocumentByteArray);
-            }
-            else
             {
-                DocumentByteArray = new byte[original.DocumentByteArray.Length];
-                Array.Copy(original.DocumentByteArray, DocumentByteArray, original.DocumentByteArray.Length);
-                FileName = original.FileName;
+                return new WmlDocument(doc);
             }
-        }
 
-        public OpenXmlPowerToolsDocument(string fileName)
-        {
-            this.FileName = fileName;
-            DocumentByteArray = File.ReadAllBytes(fileName);
-        }
-
-        public OpenXmlPowerToolsDocument(string fileName, bool convertToTransitional)
-        {
-            this.FileName = fileName;
-
-            if (convertToTransitional)
+            if (type == typeof(SpreadsheetDocument))
             {
-                var tempByteArray = File.ReadAllBytes(fileName);
-                ConvertToTransitional(fileName, tempByteArray);
+                return new SmlDocument(doc);
             }
-            else
+
+            if (type == typeof(PresentationDocument))
             {
-                this.FileName = fileName;
-                DocumentByteArray = File.ReadAllBytes(fileName);
+                return new PmlDocument(doc);
             }
+
+            return null; // This should not be possible from a valid OpenXmlPowerToolsDocument object
         }
 
         private void ConvertToTransitional(string fileName, byte[] tempByteArray)
@@ -163,7 +233,7 @@ namespace OpenXmlPowerTools
                 throw new PowerToolsDocumentException("Not an Open XML document.");
             }
 
-            using (MemoryStream ms = new MemoryStream())
+            using (var ms = new MemoryStream())
             {
                 ms.Write(tempByteArray, 0, tempByteArray.Length);
                 if (type == typeof(WordprocessingDocument))
@@ -171,15 +241,15 @@ namespace OpenXmlPowerTools
                     using (WordprocessingDocument sDoc = WordprocessingDocument.Open(ms, true))
                     {
                         // following code forces the SDK to serialize
-                        foreach (var part in sDoc.Parts)
+                        foreach (IdPartPair part in sDoc.Parts)
                         {
                             try
                             {
-                                var z = part.OpenXmlPart.RootElement;
+                                OpenXmlPartRootElement unused = part.OpenXmlPart.RootElement;
                             }
                             catch (Exception)
                             {
-                                continue;
+                                // Ignore
                             }
                         }
                     }
@@ -189,15 +259,15 @@ namespace OpenXmlPowerTools
                     using (SpreadsheetDocument sDoc = SpreadsheetDocument.Open(ms, true))
                     {
                         // following code forces the SDK to serialize
-                        foreach (var part in sDoc.Parts)
+                        foreach (IdPartPair part in sDoc.Parts)
                         {
                             try
                             {
-                                var z = part.OpenXmlPart.RootElement;
+                                OpenXmlPartRootElement unused = part.OpenXmlPart.RootElement;
                             }
                             catch (Exception)
                             {
-                                continue;
+                                // Ignore
                             }
                         }
                     }
@@ -207,63 +277,22 @@ namespace OpenXmlPowerTools
                     using (PresentationDocument sDoc = PresentationDocument.Open(ms, true))
                     {
                         // following code forces the SDK to serialize
-                        foreach (var part in sDoc.Parts)
+                        foreach (IdPartPair part in sDoc.Parts)
                         {
                             try
                             {
-                                var z = part.OpenXmlPart.RootElement;
+                                OpenXmlPartRootElement unused = part.OpenXmlPart.RootElement;
                             }
                             catch (Exception)
                             {
-                                continue;
+                                // Ignore
                             }
                         }
                     }
                 }
-                this.FileName = fileName;
-                DocumentByteArray = ms.ToArray();
-            }
-        }
-
-        public OpenXmlPowerToolsDocument(byte[] byteArray)
-        {
-            DocumentByteArray = new byte[byteArray.Length];
-            Array.Copy(byteArray, DocumentByteArray, byteArray.Length);
-            this.FileName = null;
-        }
-
-        public OpenXmlPowerToolsDocument(byte[] byteArray, bool convertToTransitional)
-        {
-            if (convertToTransitional)
-            {
-                ConvertToTransitional(null, byteArray);
-            }
-            else
-            {
-                DocumentByteArray = new byte[byteArray.Length];
-                Array.Copy(byteArray, DocumentByteArray, byteArray.Length);
-                this.FileName = null;
-            }
-        }
-
-        public OpenXmlPowerToolsDocument(string fileName, MemoryStream memStream)
-        {
-            FileName = fileName;
-            DocumentByteArray = new byte[memStream.Length];
-            Array.Copy(memStream.GetBuffer(), DocumentByteArray, memStream.Length);
-        }
 
-        public OpenXmlPowerToolsDocument(string fileName, MemoryStream memStream, bool convertToTransitional)
-        {
-            if (convertToTransitional)
-            {
-                ConvertToTransitional(fileName, memStream.ToArray());
-            }
-            else
-            {
                 FileName = fileName;
-                DocumentByteArray = new byte[memStream.Length];
-                Array.Copy(memStream.GetBuffer(), DocumentByteArray, memStream.Length);
+                DocumentByteArray = ms.ToArray();
             }
         }
 
@@ -271,7 +300,8 @@ namespace OpenXmlPowerTools
         {
             if (FileName == null)
                 return "Unnamed Document";
-            FileInfo file = new FileInfo(FileName);
+
+            var file = new FileInfo(FileName);
             return file.Name;
         }
 
@@ -282,9 +312,10 @@ namespace OpenXmlPowerTools
 
         public void Save()
         {
-            if (this.FileName == null)
+            if (FileName == null)
                 throw new InvalidOperationException("Attempting to Save a document that has no file name.  Use SaveAs instead.");
-            File.WriteAllBytes(this.FileName, DocumentByteArray);
+
+            File.WriteAllBytes(FileName, DocumentByteArray);
         }
 
         public void WriteByteArray(Stream stream)
@@ -299,17 +330,24 @@ namespace OpenXmlPowerTools
 
         private static Type GetDocumentType(byte[] bytes)
         {
-            using (MemoryStream stream = new MemoryStream())
+            // Relationship types:
+            const string coreDocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
+            const string strictCoreDocument = "http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument";
+
+            using (var stream = new MemoryStream())
             {
                 stream.Write(bytes, 0, bytes.Length);
                 using (Package package = Package.Open(stream, FileMode.Open))
                 {
-                    PackageRelationship relationship = package.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument").FirstOrDefault();
-                    if (relationship == null)
-                        relationship = package.GetRelationshipsByType("http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument").FirstOrDefault();
+                    PackageRelationship relationship =
+                        package.GetRelationshipsByType(coreDocument).FirstOrDefault() ??
+                        package.GetRelationshipsByType(strictCoreDocument).FirstOrDefault();
+
                     if (relationship != null)
                     {
-                        PackagePart part = package.GetPart(PackUriHelper.ResolvePartUri(relationship.SourceUri, relationship.TargetUri));
+                        Uri partUri = PackUriHelper.ResolvePartUri(relationship.SourceUri, relationship.TargetUri);
+                        PackagePart part = package.GetPart(partUri);
+
                         switch (part.ContentType)
                         {
                             case "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml":
@@ -317,11 +355,13 @@ namespace OpenXmlPowerTools
                             case "application/vnd.ms-word.template.macroEnabledTemplate.main+xml":
                             case "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml":
                                 return typeof(WordprocessingDocument);
+
                             case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml":
                             case "application/vnd.ms-excel.sheet.macroEnabled.main+xml":
                             case "application/vnd.ms-excel.template.macroEnabled.main+xml":
                             case "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml":
                                 return typeof(SpreadsheetDocument);
+
                             case "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml":
                             case "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml":
                             case "application/vnd.ms-powerpoint.template.macroEnabled.main+xml":
@@ -329,9 +369,12 @@ namespace OpenXmlPowerTools
                             case "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml":
                             case "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml":
                                 return typeof(PresentationDocument);
+
+                            default:
+                                return typeof(Package);
                         }
-                        return typeof(Package);
                     }
+
                     return null;
                 }
             }
@@ -340,7 +383,7 @@ namespace OpenXmlPowerTools
         public static void SavePartAs(OpenXmlPart part, string filePath)
         {
             Stream partStream = part.GetStream(FileMode.Open, FileAccess.Read);
-            byte[] partContent = new byte[partStream.Length];
+            var partContent = new byte[partStream.Length];
             partStream.Read(partContent, 0, (int)partStream.Length);
 
             File.WriteAllBytes(filePath, partContent);
@@ -520,18 +563,19 @@ namespace OpenXmlPowerTools
 
     public class OpenXmlMemoryStreamDocument : IDisposable
     {
-        private OpenXmlPowerToolsDocument Document;
-        private MemoryStream DocMemoryStream;
-        private Package DocPackage;
+        private readonly OpenXmlPowerToolsDocument _document;
+        private MemoryStream _docMemoryStream;
+        private Package _docPackage;
 
         public OpenXmlMemoryStreamDocument(OpenXmlPowerToolsDocument doc)
         {
-            Document = doc;
-            DocMemoryStream = new MemoryStream();
-            DocMemoryStream.Write(doc.DocumentByteArray, 0, doc.DocumentByteArray.Length);
+            _document = doc;
+            _docMemoryStream = new MemoryStream();
+            _docMemoryStream.Write(doc.DocumentByteArray, 0, doc.DocumentByteArray.Length);
+
             try
             {
-                DocPackage = Package.Open(DocMemoryStream, FileMode.Open);
+                _docPackage = Package.Open(_docMemoryStream, FileMode.Open);
             }
             catch (Exception e)
             {
@@ -541,10 +585,11 @@ namespace OpenXmlPowerTools
 
         internal OpenXmlMemoryStreamDocument(MemoryStream stream)
         {
-            DocMemoryStream = stream;
+            _docMemoryStream = stream;
+
             try
             {
-                DocPackage = Package.Open(DocMemoryStream, FileMode.Open);
+                _docPackage = Package.Open(_docMemoryStream, FileMode.Open);
             }
             catch (Exception e)
             {
@@ -552,10 +597,15 @@ namespace OpenXmlPowerTools
             }
         }
 
+        public void Dispose()
+        {
+            Dispose(true);
+        }
+
         public static OpenXmlMemoryStreamDocument CreateWordprocessingDocument()
         {
-            MemoryStream stream = new MemoryStream();
-            using (WordprocessingDocument doc = WordprocessingDocument.Create(stream, DocumentFormat.OpenXml.WordprocessingDocumentType.Document))
+            var stream = new MemoryStream();
+            using (WordprocessingDocument doc = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document))
             {
                 doc.AddMainDocumentPart();
                 doc.MainDocumentPart.PutXDocument(new XDocument(
@@ -567,10 +617,11 @@ namespace OpenXmlPowerTools
                 return new OpenXmlMemoryStreamDocument(stream);
             }
         }
+
         public static OpenXmlMemoryStreamDocument CreateSpreadsheetDocument()
         {
-            MemoryStream stream = new MemoryStream();
-            using (SpreadsheetDocument doc = SpreadsheetDocument.Create(stream, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
+            var stream = new MemoryStream();
+            using (SpreadsheetDocument doc = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook))
             {
                 doc.AddWorkbookPart();
                 XNamespace ns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
@@ -584,10 +635,11 @@ namespace OpenXmlPowerTools
                 return new OpenXmlMemoryStreamDocument(stream);
             }
         }
+
         public static OpenXmlMemoryStreamDocument CreatePresentationDocument()
         {
-            MemoryStream stream = new MemoryStream();
-            using (PresentationDocument doc = PresentationDocument.Create(stream, DocumentFormat.OpenXml.PresentationDocumentType.Presentation))
+            var stream = new MemoryStream();
+            using (PresentationDocument doc = PresentationDocument.Create(stream, PresentationDocumentType.Presentation))
             {
                 doc.AddPresentationPart();
                 XNamespace ns = "http://schemas.openxmlformats.org/presentationml/2006/main";
@@ -608,7 +660,7 @@ namespace OpenXmlPowerTools
 
         public static OpenXmlMemoryStreamDocument CreatePackage()
         {
-            MemoryStream stream = new MemoryStream();
+            var stream = new MemoryStream();
             Package package = Package.Open(stream, FileMode.Create);
             package.Close();
             return new OpenXmlMemoryStreamDocument(stream);
@@ -616,7 +668,7 @@ namespace OpenXmlPowerTools
 
         public Package GetPackage()
         {
-            return DocPackage;
+            return _docPackage;
         }
 
         public WordprocessingDocument GetWordprocessingDocument()
@@ -625,20 +677,23 @@ namespace OpenXmlPowerTools
             {
                 if (GetDocumentType() != typeof(WordprocessingDocument))
                     throw new PowerToolsDocumentException("Not a Wordprocessing document.");
-                return WordprocessingDocument.Open(DocPackage);
+
+                return WordprocessingDocument.Open(_docPackage);
             }
             catch (Exception e)
             {
                 throw new PowerToolsDocumentException(e.Message);
             }
         }
+
         public SpreadsheetDocument GetSpreadsheetDocument()
         {
             try
             {
                 if (GetDocumentType() != typeof(SpreadsheetDocument))
                     throw new PowerToolsDocumentException("Not a Spreadsheet document.");
-                return SpreadsheetDocument.Open(DocPackage);
+
+                return SpreadsheetDocument.Open(_docPackage);
             }
             catch (Exception e)
             {
@@ -652,7 +707,8 @@ namespace OpenXmlPowerTools
             {
                 if (GetDocumentType() != typeof(PresentationDocument))
                     throw new PowerToolsDocumentException("Not a Presentation document.");
-                return PresentationDocument.Open(DocPackage);
+
+                return PresentationDocument.Open(_docPackage);
             }
             catch (Exception e)
             {
@@ -662,12 +718,23 @@ namespace OpenXmlPowerTools
 
         public Type GetDocumentType()
         {
-            PackageRelationship relationship = DocPackage.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument").FirstOrDefault();
+            PackageRelationship relationship = _docPackage
+                .GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")
+                .FirstOrDefault();
+
             if (relationship == null)
-                relationship = DocPackage.GetRelationshipsByType("http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument").FirstOrDefault();
+            {
+                relationship = _docPackage
+                    .GetRelationshipsByType("http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument")
+                    .FirstOrDefault();
+            }
+
             if (relationship == null)
+            {
                 throw new PowerToolsDocumentException("Not an Open XML Document.");
-            PackagePart part = DocPackage.GetPart(PackUriHelper.ResolvePartUri(relationship.SourceUri, relationship.TargetUri));
+            }
+
+            PackagePart part = _docPackage.GetPart(PackUriHelper.ResolvePartUri(relationship.SourceUri, relationship.TargetUri));
             switch (part.ContentType)
             {
                 case "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml":
@@ -675,11 +742,13 @@ namespace OpenXmlPowerTools
                 case "application/vnd.ms-word.template.macroEnabledTemplate.main+xml":
                 case "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml":
                     return typeof(WordprocessingDocument);
+
                 case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml":
                 case "application/vnd.ms-excel.sheet.macroEnabled.main+xml":
                 case "application/vnd.ms-excel.template.macroEnabled.main+xml":
                 case "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml":
                     return typeof(SpreadsheetDocument);
+
                 case "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml":
                 case "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml":
                 case "application/vnd.ms-powerpoint.template.macroEnabled.main+xml":
@@ -688,35 +757,36 @@ namespace OpenXmlPowerTools
                 case "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml":
                     return typeof(PresentationDocument);
             }
+
             return null;
         }
 
         public OpenXmlPowerToolsDocument GetModifiedDocument()
         {
-            DocPackage.Close();
-            DocPackage = null;
-            return new OpenXmlPowerToolsDocument((Document == null) ? null : Document.FileName, DocMemoryStream);
+            _docPackage.Close();
+            _docPackage = null;
+            return new OpenXmlPowerToolsDocument(_document?.FileName, _docMemoryStream);
         }
 
         public WmlDocument GetModifiedWmlDocument()
         {
-            DocPackage.Close();
-            DocPackage = null;
-            return new WmlDocument((Document == null) ? null : Document.FileName, DocMemoryStream);
+            _docPackage.Close();
+            _docPackage = null;
+            return new WmlDocument(_document?.FileName, _docMemoryStream);
         }
 
         public SmlDocument GetModifiedSmlDocument()
         {
-            DocPackage.Close();
-            DocPackage = null;
-            return new SmlDocument((Document == null) ? null : Document.FileName, DocMemoryStream);
+            _docPackage.Close();
+            _docPackage = null;
+            return new SmlDocument(_document?.FileName, _docMemoryStream);
         }
 
         public PmlDocument GetModifiedPmlDocument()
         {
-            DocPackage.Close();
-            DocPackage = null;
-            return new PmlDocument((Document == null) ? null : Document.FileName, DocMemoryStream);
+            _docPackage.Close();
+            _docPackage = null;
+            return new PmlDocument(_document?.FileName, _docMemoryStream);
         }
 
         public void Close()
@@ -724,33 +794,27 @@ namespace OpenXmlPowerTools
             Dispose(true);
         }
 
-        public void Dispose()
-        {
-            Dispose(true);
-        }
-
         ~OpenXmlMemoryStreamDocument()
         {
             Dispose(false);
         }
 
-        private void Dispose(Boolean disposing)
+        private void Dispose(bool disposing)
         {
             if (disposing)
             {
-                if (DocPackage != null)
-                {
-                    DocPackage.Close();
-                }
-                if (DocMemoryStream != null)
-                {
-                    DocMemoryStream.Dispose();
-                }
+                _docPackage?.Close();
+                _docMemoryStream?.Dispose();
             }
-            if (DocPackage == null && DocMemoryStream == null)
+
+            if (_docPackage == null && _docMemoryStream == null)
+            {
                 return;
-            DocPackage = null;
-            DocMemoryStream = null;
+            }
+
+            _docPackage = null;
+            _docMemoryStream = null;
+
             GC.SuppressFinalize(this);
         }
     }

+ 294 - 143
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PtOpenXmlUtil.cs

@@ -24,22 +24,23 @@ namespace OpenXmlPowerTools
     {
         public static XDocument GetXDocument(this OpenXmlPart part)
         {
-            if (part == null) throw new ArgumentNullException("part");
+            if (part == null) throw new ArgumentNullException(nameof(part));
 
-            XDocument partXDocument = part.Annotation<XDocument>();
+            var partXDocument = part.Annotation<XDocument>();
             if (partXDocument != null) return partXDocument;
 
             using (Stream partStream = part.GetStream())
             {
                 if (partStream.Length == 0)
                 {
-                    partXDocument = new XDocument();
-                    partXDocument.Declaration = new XDeclaration("1.0", "UTF-8", "yes");
+                    partXDocument = new XDocument { Declaration = new XDeclaration("1.0", "UTF-8", "yes") };
                 }
                 else
                 {
                     using (XmlReader partXmlReader = XmlReader.Create(partStream))
+                    {
                         partXDocument = XDocument.Load(partXmlReader);
+                    }
                 }
             }
 
@@ -49,10 +50,10 @@ namespace OpenXmlPowerTools
 
         public static XDocument GetXDocument(this OpenXmlPart part, out XmlNamespaceManager namespaceManager)
         {
-            if (part == null) throw new ArgumentNullException("part");
+            if (part == null) throw new ArgumentNullException(nameof(part));
 
             namespaceManager = part.Annotation<XmlNamespaceManager>();
-            XDocument partXDocument = part.Annotation<XDocument>();
+            var partXDocument = part.Annotation<XDocument>();
             if (partXDocument != null)
             {
                 if (namespaceManager != null) return partXDocument;
@@ -67,101 +68,148 @@ namespace OpenXmlPowerTools
             {
                 if (partStream.Length == 0)
                 {
-                    partXDocument = new XDocument();
-                    partXDocument.Declaration = new XDeclaration("1.0", "UTF-8", "yes");
-
+                    partXDocument = new XDocument { Declaration = new XDeclaration("1.0", "UTF-8", "yes") };
                     part.AddAnnotation(partXDocument);
 
                     return partXDocument;
                 }
-                else
+
+                using (XmlReader partXmlReader = XmlReader.Create(partStream))
                 {
-                    using (XmlReader partXmlReader = XmlReader.Create(partStream))
-                    {
-                        partXDocument = XDocument.Load(partXmlReader);
-                        namespaceManager = new XmlNamespaceManager(partXmlReader.NameTable);
+                    partXDocument = XDocument.Load(partXmlReader);
+                    XmlNameTable nameTable = partXmlReader.NameTable ?? throw new Exception("NameTable is null.");
+                    namespaceManager = new XmlNamespaceManager(nameTable);
 
-                        part.AddAnnotation(partXDocument);
-                        part.AddAnnotation(namespaceManager);
+                    part.AddAnnotation(partXDocument);
+                    part.AddAnnotation(namespaceManager);
 
-                        return partXDocument;
-                    }
+                    return partXDocument;
                 }
             }
         }
 
+        /// <summary>
+        /// Gets the given <see cref="OpenXmlPart" />'s root <see cref="XElement" />.
+        /// </summary>
+        /// <param name="part">The <see cref="OpenXmlPart" />.</param>
+        /// <returns>The root <see cref="XElement" />.</returns>
+        public static XElement GetXElement(this OpenXmlPart part)
+        {
+            if (part == null) throw new ArgumentNullException(nameof(part));
+
+            return part.GetXDocument().Root ?? throw new ArgumentException("Part does not contain a root element.");
+        }
+
+        /// <summary>
+        /// Saves the cached <see cref="XDocument"/> to the the given <see cref="OpenXmlPart"/>.
+        /// </summary>
+        /// <param name="part">The <see cref="OpenXmlPart"/>.</param>
         public static void PutXDocument(this OpenXmlPart part)
         {
-            if (part == null) throw new ArgumentNullException("part");
+            if (part == null) throw new ArgumentNullException(nameof(part));
 
             XDocument partXDocument = part.GetXDocument();
             if (partXDocument != null)
             {
-#if true
                 using (Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write))
                 using (XmlWriter partXmlWriter = XmlWriter.Create(partStream))
+                {
                     partXDocument.Save(partXmlWriter);
-#else
-                byte[] array = Encoding.UTF8.GetBytes(partXDocument.ToString(SaveOptions.DisableFormatting));
-                using (MemoryStream ms = new MemoryStream(array))
-                    part.FeedData(ms);
-#endif
+                }
             }
         }
 
+        /// <summary>
+        /// Saves the cached <see cref="XDocument"/> to the the given <see cref="OpenXmlPart"/>,
+        /// indending the XML markup and creating new lines for attributes.
+        /// </summary>
+        /// <param name="part">The <see cref="OpenXmlPart"/>.</param>
         public static void PutXDocumentWithFormatting(this OpenXmlPart part)
         {
-            if (part == null) throw new ArgumentNullException("part");
+            if (part == null) throw new ArgumentNullException(nameof(part));
 
             XDocument partXDocument = part.GetXDocument();
             if (partXDocument != null)
             {
                 using (Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write))
                 {
-                    XmlWriterSettings settings = new XmlWriterSettings();
-                    settings.Indent = true;
-                    settings.OmitXmlDeclaration = true;
-                    settings.NewLineOnAttributes = true;
+                    var settings = new XmlWriterSettings
+                    {
+                        Indent = true,
+                        OmitXmlDeclaration = true,
+                        NewLineOnAttributes = true
+                    };
+
                     using (XmlWriter partXmlWriter = XmlWriter.Create(partStream, settings))
+                    {
                         partXDocument.Save(partXmlWriter);
+                    }
                 }
             }
         }
 
         public static void PutXDocument(this OpenXmlPart part, XDocument document)
         {
-            if (part == null) throw new ArgumentNullException("part");
-            if (document == null) throw new ArgumentNullException("document");
+            if (part == null) throw new ArgumentNullException(nameof(part));
+            if (document == null) throw new ArgumentNullException(nameof(document));
 
-            using (Stream partStream = part.GetStream(FileMode.Open, FileAccess.Read))
+            using (Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write))
             using (XmlWriter partXmlWriter = XmlWriter.Create(partStream))
+            {
                 document.Save(partXmlWriter);
+            }
 
             part.RemoveAnnotations<XDocument>();
             part.AddAnnotation(document);
         }
 
+        /// <summary>
+        /// Writes the cached root <see cref="XElement" /> to the given <see cref="OpenXmlPart" />.
+        /// </summary>
+        /// <param name="part">The <see cref="OpenXmlPart"/>.</param>
+        public static void PutXElement(this OpenXmlPart part)
+        {
+            if (part == null) throw new ArgumentNullException(nameof(part));
+
+            part.PutXDocument();
+        }
+
+        /// <summary>
+        /// Writes the given root <see cref="XElement" /> to the given <see cref="OpenXmlPart" />.
+        /// </summary>
+        /// <param name="part">The <see cref="OpenXmlPart" />.</param>
+        /// <param name="root">The root <see cref="XElement" />.</param>
+        public static void PutXElement(this OpenXmlPart part, XElement root)
+        {
+            if (root == null) throw new ArgumentNullException(nameof(root));
+
+            PutXDocument(part, new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), root));
+        }
+
         private static XmlNamespaceManager GetManagerFromXDocument(XDocument xDocument)
         {
             XmlReader reader = xDocument.CreateReader();
             XDocument newXDoc = XDocument.Load(reader);
 
-            XElement rootElement = xDocument.Elements().FirstOrDefault();
+            XElement rootElement = xDocument.Elements().First();
             rootElement.ReplaceWith(newXDoc.Root);
 
-            XmlNameTable nameTable = reader.NameTable;
-            XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
+            XmlNameTable nameTable = reader.NameTable ?? throw new Exception("NameTable is null.");
+            var namespaceManager = new XmlNamespaceManager(nameTable);
             return namespaceManager;
         }
 
         public static IEnumerable<XElement> LogicalChildrenContent(this XElement element)
         {
             if (element.Name == W.document)
+            {
                 return element.Descendants(W.body).Take(1);
+            }
 
             if (element.Name == W.body ||
                 element.Name == W.tc ||
                 element.Name == W.txbxContent)
+            {
                 return element
                     .DescendantsTrimmed(e =>
                         e.Name == W.tbl ||
@@ -169,32 +217,42 @@ namespace OpenXmlPowerTools
                     .Where(e =>
                         e.Name == W.p ||
                         e.Name == W.tbl);
+            }
 
             if (element.Name == W.tbl)
+            {
                 return element
                     .DescendantsTrimmed(W.tr)
                     .Where(e => e.Name == W.tr);
+            }
 
             if (element.Name == W.tr)
+            {
                 return element
                     .DescendantsTrimmed(W.tc)
                     .Where(e => e.Name == W.tc);
+            }
 
             if (element.Name == W.p)
+            {
                 return element
                     .DescendantsTrimmed(e => e.Name == W.r ||
-                        e.Name == W.pict ||
-                        e.Name == W.drawing)
+                                             e.Name == W.pict ||
+                                             e.Name == W.drawing)
                     .Where(e => e.Name == W.r ||
-                        e.Name == W.pict ||
-                        e.Name == W.drawing);
+                                e.Name == W.pict ||
+                                e.Name == W.drawing);
+            }
 
             if (element.Name == W.r)
+            {
                 return element
                     .DescendantsTrimmed(e => W.SubRunLevelContent.Contains(e.Name))
                     .Where(e => W.SubRunLevelContent.Contains(e.Name));
+            }
 
             if (element.Name == MC.AlternateContent)
+            {
                 return element
                     .DescendantsTrimmed(e =>
                         e.Name == W.pict ||
@@ -203,11 +261,14 @@ namespace OpenXmlPowerTools
                     .Where(e =>
                         e.Name == W.pict ||
                         e.Name == W.drawing);
+            }
 
             if (element.Name == W.pict || element.Name == W.drawing)
+            {
                 return element
                     .DescendantsTrimmed(W.txbxContent)
                     .Where(e => e.Name == W.txbxContent);
+            }
 
             return XElement.EmptySequence;
         }
@@ -235,10 +296,10 @@ namespace OpenXmlPowerTools
         {
             yield return doc.MainDocumentPart;
 
-            foreach (var hdr in doc.MainDocumentPart.HeaderParts)
+            foreach (HeaderPart hdr in doc.MainDocumentPart.HeaderParts)
                 yield return hdr;
 
-            foreach (var ftr in doc.MainDocumentPart.FooterParts)
+            foreach (FooterPart ftr in doc.MainDocumentPart.FooterParts)
                 yield return ftr;
 
             if (doc.MainDocumentPart.FootnotesPart != null)
@@ -249,17 +310,17 @@ namespace OpenXmlPowerTools
         }
 
         /// <summary>
-        /// Creates a complete list of all parts contained in the <see cref="OpenXmlPartContainer"/>.
+        /// Creates a complete list of all parts contained in the <see cref="OpenXmlPartContainer" />.
         /// </summary>
         /// <param name="container">
-        /// A <see cref="WordprocessingDocument"/>, <see cref="SpreadsheetDocument"/>, or
-        /// <see cref="PresentationDocument"/>.
+        /// A <see cref="WordprocessingDocument" />, <see cref="SpreadsheetDocument" />, or
+        /// <see cref="PresentationDocument" />.
         /// </param>
-        /// <returns>list of <see cref="OpenXmlPart"/>s contained in the <see cref="OpenXmlPartContainer"/>.</returns>
+        /// <returns>list of <see cref="OpenXmlPart" />s contained in the <see cref="OpenXmlPartContainer" />.</returns>
         public static List<OpenXmlPart> GetAllParts(this OpenXmlPartContainer container)
         {
             // Use a HashSet so that parts are processed only once.
-            HashSet<OpenXmlPart> partList = new HashSet<OpenXmlPart>();
+            var partList = new HashSet<OpenXmlPart>();
 
             foreach (IdPartPair p in container.Parts)
                 AddPart(partList, p.OpenXmlPart);
@@ -275,6 +336,42 @@ namespace OpenXmlPowerTools
             foreach (IdPartPair p in part.Parts)
                 AddPart(partList, p.OpenXmlPart);
         }
+
+        public static void IgnoreNamespace(this XElement root, string prefix, XNamespace @namespace)
+        {
+            // Declare markup compatibility extensions namespace as necessary.
+            if (root.Attributes().All(a => a.Value != MC.mc.NamespaceName))
+            {
+                root.Add(new XAttribute(XNamespace.Xmlns + "mc", MC.mc.NamespaceName));
+            }
+
+            // Declare ignored namespace as necessary.
+            string namespaceName = @namespace.NamespaceName;
+            bool IsIgnoredNamespaceDeclaration(XAttribute a) => a.Name.Namespace == XNamespace.Xmlns && a.Value == namespaceName;
+            XAttribute attribute = root.Attributes().FirstOrDefault(IsIgnoredNamespaceDeclaration);
+            if (attribute == null)
+            {
+                attribute = new XAttribute(XNamespace.Xmlns + prefix, namespaceName);
+                root.Add(attribute);
+            }
+
+            string effectivePrefix = root.GetPrefixOfNamespace(@namespace);
+
+            // Add prefix to mc:Ignorable attribute value.
+            var ignorable = (string)root.Attribute(MC.Ignorable);
+            if (ignorable != null)
+            {
+                string[] list = ignorable.Split(' ');
+                if (!list.Contains(effectivePrefix))
+                {
+                    root.SetAttributeValue(MC.Ignorable, ignorable + " " + effectivePrefix);
+                }
+            }
+            else
+            {
+                root.Add(new XAttribute(MC.Ignorable, effectivePrefix));
+            }
+        }
     }
 
     public static class FlatOpc
@@ -616,11 +713,10 @@ namespace OpenXmlPowerTools
     {
         public static XAttribute GetXmlSpaceAttribute(string value)
         {
-            return (value.Length > 0) && ((value[0] == ' ') || (value[value.Length - 1] == ' '))
+            return value.Length > 0 && (value[0] == ' ' || value[value.Length - 1] == ' ')
                 ? new XAttribute(XNamespace.Xml + "space", "preserve")
                 : null;
         }
-
         public static XAttribute GetXmlSpaceAttribute(char value)
         {
             return value == ' ' ? new XAttribute(XNamespace.Xml + "space", "preserve") : null;
@@ -629,16 +725,16 @@ namespace OpenXmlPowerTools
 
     public static class WordprocessingMLUtil
     {
-        private static HashSet<string> UnknownFonts = new HashSet<string>();
-        private static HashSet<string> KnownFamilies = null;
+        private static readonly HashSet<string> UnknownFonts = new HashSet<string>();
+        private static HashSet<string> KnownFamilies;
 
         public static int CalcWidthOfRunInTwips(XElement r)
         {
             if (KnownFamilies == null)
             {
                 KnownFamilies = new HashSet<string>();
-                var families = FontFamily.Families;
-                foreach (var fam in families)
+                FontFamily[] families = FontFamily.Families;
+                foreach (FontFamily fam in families)
                     KnownFamilies.Add(fam.Name);
             }
 
@@ -650,7 +746,7 @@ namespace OpenXmlPowerTools
             if (UnknownFonts.Contains(fontName))
                 return 0;
 
-            var rPr = r.Element(W.rPr);
+            XElement rPr = r.Element(W.rPr);
             if (rPr == null)
                 throw new OpenXmlPowerToolsException("Internal Error, should have run properties");
             var languageType = (string)r.Attribute(PtOpenXml.LanguageType);
@@ -662,7 +758,7 @@ namespace OpenXmlPowerTools
             if (szn == null)
                 szn = 22m;
 
-            var sz = szn.GetValueOrDefault();
+            decimal sz = szn.GetValueOrDefault();
 
             // unknown font families will throw ArgumentException, in which case just return 0
             if (!KnownFamilies.Contains(fontName))
@@ -679,9 +775,9 @@ namespace OpenXmlPowerTools
 
                 return 0;
             }
-            FontStyle fs = FontStyle.Regular;
-            var bold = GetBoolProp(rPr, W.b) || GetBoolProp(rPr, W.bCs);
-            var italic = GetBoolProp(rPr, W.i) || GetBoolProp(rPr, W.iCs);
+            var fs = FontStyle.Regular;
+            bool bold = GetBoolProp(rPr, W.b) || GetBoolProp(rPr, W.bCs);
+            bool italic = GetBoolProp(rPr, W.i) || GetBoolProp(rPr, W.iCs);
             if (bold && !italic)
                 fs = FontStyle.Bold;
             if (italic && !bold)
@@ -689,12 +785,13 @@ namespace OpenXmlPowerTools
             if (bold && italic)
                 fs = FontStyle.Bold | FontStyle.Italic;
 
-            var runText = r.DescendantsTrimmed(W.txbxContent)
+
+            string runText = r.DescendantsTrimmed(W.txbxContent)
                 .Where(e => e.Name == W.t)
                 .Select(t => (string)t)
                 .StringConcatenate();
 
-            var tabLength = r.DescendantsTrimmed(W.txbxContent)
+            decimal tabLength = r.DescendantsTrimmed(W.txbxContent)
                 .Where(e => e.Name == W.tab)
                 .Select(t => (decimal)t.Attribute(PtOpenXml.TabWidth))
                 .Sum();
@@ -702,7 +799,7 @@ namespace OpenXmlPowerTools
             if (runText.Length == 0 && tabLength == 0)
                 return 0;
 
-            int multiplier = 1;
+            var multiplier = 1;
             if (runText.Length <= 2)
                 multiplier = 100;
             else if (runText.Length <= 4)
@@ -715,33 +812,65 @@ namespace OpenXmlPowerTools
                 multiplier = 6;
             if (multiplier != 1)
             {
-                StringBuilder sb = new StringBuilder();
-                for (int i = 0; i < multiplier; i++)
+                var sb = new StringBuilder();
+                for (var i = 0; i < multiplier; i++)
                     sb.Append(runText);
                 runText = sb.ToString();
             }
 
-            var w = MetricsGetter.GetTextWidth(ff, fs, sz, runText);
+            int w = MetricsGetter.GetTextWidth(ff, fs, sz, runText);
 
             return (int) (w / 96m * 1440m / multiplier + tabLength * 1440m);
         }
 
         public static bool GetBoolProp(XElement runProps, XName xName)
         {
-            var p = runProps.Element(xName);
+            XElement p = runProps.Element(xName);
             if (p == null)
                 return false;
-            var v = p.Attribute(W.val);
+
+            XAttribute v = p.Attribute(W.val);
             if (v == null)
                 return true;
-            var s = v.Value.ToLower();
+
+            string s = v.Value.ToLower();
             if (s == "0" || s == "false")
                 return false;
             if (s == "1" || s == "true")
                 return true;
+
             return false;
         }
+        public static int StringToTwips(string twipsOrPoints)
+        {
+            // if the pos value is in points, not twips
+            if (twipsOrPoints.EndsWith("pt"))
+            {
+                decimal decimalValue = decimal.Parse(twipsOrPoints.Substring(0, twipsOrPoints.Length - 2));
+                return (int)(decimalValue * 20);
+            }
+
+            return int.Parse(twipsOrPoints);
+        }
+
+        public static int? AttributeToTwips(XAttribute attribute)
+        {
+            if (attribute == null)
+            {
+                return null;
+            }
 
+            var twipsOrPoints = (string)attribute;
+
+            // if the pos value is in points, not twips
+            if (twipsOrPoints.EndsWith("pt"))
+            {
+                decimal decimalValue = decimal.Parse(twipsOrPoints.Substring(0, twipsOrPoints.Length - 2));
+                return (int)(decimalValue * 20);
+            }
+
+            return int.Parse(twipsOrPoints);
+        }
         private static readonly List<XName> AdditionalRunContainerNames = new List<XName>
         {
             W.w + "bdo",
@@ -768,6 +897,9 @@ namespace OpenXmlPowerTools
                             if (ce.Elements().Count(e => e.Name != W.rPr) != 1)
                                 return dontConsolidate;
 
+                            if (ce.Attribute(PtOpenXml.AbstractNumId) != null)
+                                return dontConsolidate;
+
                             XElement rPr = ce.Element(W.rPr);
                             string rPrString = rPr != null ? rPr.ToString(SaveOptions.None) : string.Empty;
 
@@ -818,8 +950,8 @@ namespace OpenXmlPowerTools
                             }
 
                             // w:ins/w:r/w:t
-                            if ((ce.Elements().Elements().Count(e => e.Name != W.rPr) != 1) ||
-                                !ce.Elements().Elements(W.t).Any())
+                            if (ce.Elements().Elements().Count(e => e.Name != W.rPr) != 1 ||
+                              !ce.Elements().Elements(W.t).Any())
                                 return dontConsolidate;
 
                             XAttribute dateIns2 = ce.Attribute(W.date);
@@ -829,7 +961,7 @@ namespace OpenXmlPowerTools
                                 ? ((DateTime) dateIns2).ToString("s")
                                 : string.Empty;
 
-                            string idIns2 = (string)ce.Attribute(W.id);
+                            var idIns2 = (string)ce.Attribute(W.id);
 
                             return "Wins2" +
                                    authorIns2 +
@@ -843,7 +975,7 @@ namespace OpenXmlPowerTools
 
                         if (ce.Name == W.del)
                         {
-                            if ((ce.Elements(W.r).Elements().Count(e => e.Name != W.rPr) != 1) ||
+                            if (ce.Elements(W.r).Elements().Count(e => e.Name != W.rPr) != 1 ||
                                 !ce.Elements().Elements(W.delText).Any())
                                 return dontConsolidate;
 
@@ -869,12 +1001,12 @@ namespace OpenXmlPowerTools
                 groupedAdjacentRunsWithIdenticalFormatting.Select(g =>
                 {
                     if (g.Key == dontConsolidate)
-                        return (object) g;
+                        return (object)g;
 
                     string textValue = g
                         .Select(r =>
                             r.Descendants()
-                                .Where(d => (d.Name == W.t) || (d.Name == W.delText) || (d.Name == W.instrText))
+                                .Where(d => d.Name == W.t || d.Name == W.delText || d.Name == W.instrText)
                                 .Select(d => d.Value)
                                 .StringConcatenate())
                         .StringConcatenate();
@@ -887,52 +1019,50 @@ namespace OpenXmlPowerTools
                             IEnumerable<IEnumerable<XAttribute>> statusAtt =
                                 g.Select(r => r.Descendants(W.t).Take(1).Attributes(PtOpenXml.Status));
                             return new XElement(W.r,
+                                g.First().Attributes(),
                                 g.First().Elements(W.rPr),
                                 new XElement(W.t, statusAtt, xs, textValue));
                         }
 
                         if (g.First().Element(W.instrText) != null)
                             return new XElement(W.r,
+                                g.First().Attributes(),
                                 g.First().Elements(W.rPr),
                                 new XElement(W.instrText, xs, textValue));
                     }
 
                     if (g.First().Name == W.ins)
                     {
-#if false
-                        if (g.First().Elements(W.del).Any())
-                            return new XElement(W.ins,
-                                g.First().Attributes(),
-                                new XElement(W.del,
-                                    g.First().Elements(W.del).Attributes(),
-                                    new XElement(W.r,
-                                        g.First().Elements(W.del).Elements(W.r).Elements(W.rPr),
-                                        new XElement(W.delText, xs, textValue))));
-#endif
+                        XElement firstR = g.First().Element(W.r);
                         return new XElement(W.ins,
                             g.First().Attributes(),
                             new XElement(W.r,
+                                firstR?.Attributes(),
                                 g.First().Elements(W.r).Elements(W.rPr),
                                 new XElement(W.t, xs, textValue)));
                     }
 
                     if (g.First().Name == W.del)
+                    {
+                        XElement firstR = g.First().Element(W.r);
                         return new XElement(W.del,
                             g.First().Attributes(),
                             new XElement(W.r,
+                                firstR?.Attributes(),
                                 g.First().Elements(W.r).Elements(W.rPr),
                                 new XElement(W.delText, xs, textValue)));
+                    }
 
                     return g;
                 }));
 
             // Process w:txbxContent//w:p
             foreach (XElement txbx in runContainerWithConsolidatedRuns.Descendants(W.txbxContent))
-                foreach (XElement txbxPara in txbx.DescendantsTrimmed(W.txbxContent).Where(d => d.Name == W.p))
-                {
-                    XElement newPara = CoalesceAdjacentRunsWithIdenticalFormatting(txbxPara);
-                    txbxPara.ReplaceWith(newPara);
-                }
+            foreach (XElement txbxPara in txbx.DescendantsTrimmed(W.txbxContent).Where(d => d.Name == W.p))
+            {
+                XElement newPara = CoalesceAdjacentRunsWithIdenticalFormatting(txbxPara);
+                txbxPara.ReplaceWith(newPara);
+            }
 
             // Process additional run containers.
             List<XElement> runContainers = runContainerWithConsolidatedRuns
@@ -948,7 +1078,7 @@ namespace OpenXmlPowerTools
             return runContainerWithConsolidatedRuns;
         }
 
-        private static Dictionary<XName, int> Order_settings = new Dictionary<XName, int>
+        private static readonly Dictionary<XName, int> Order_settings = new Dictionary<XName, int>
         {
             { W.writeProtection, 10}, 
             { W.view, 20}, 
@@ -1045,7 +1175,7 @@ namespace OpenXmlPowerTools
             //{W.sl:schemaLibrary, 930}, 
             { W.doNotEmbedSmartTags, 940}, 
             { W.decimalSymbol, 950}, 
-            { W.listSeparator, 960}, 
+            { W.listSeparator, 960},
         };
 
 #if false
@@ -1149,7 +1279,7 @@ decimalSymbol
 listSeparator
 #endif
 
-        private static Dictionary<XName, int> Order_pPr = new Dictionary<XName, int>
+        private static readonly Dictionary<XName, int> Order_pPr = new Dictionary<XName, int>
         {
             { W.pStyle, 10 },
             { W.keepNext, 20 },
@@ -1186,11 +1316,13 @@ listSeparator
             { W.cnfStyle, 340 },
             { W.rPr, 350 },
             { W.sectPr, 360 },
-            { W.pPrChange, 370 },
+            { W.pPrChange, 370 }
         };
 
-        private static Dictionary<XName, int> Order_rPr = new Dictionary<XName, int>
-        {
+        private static readonly Dictionary<XName, int> Order_rPr = new Dictionary<XName, int>
+        {  
+            { W.moveFrom, 5 },
+            { W.moveTo, 7 },
             { W.ins, 10 },
             { W.del, 20 },
             { W.rStyle, 30 },
@@ -1236,10 +1368,10 @@ listSeparator
             { W.lang, 430 },
             { W.eastAsianLayout, 440 },
             { W.specVanish, 450 },
-            { W.oMath, 460 },
+            { W.oMath, 460 }
         };
 
-        private static Dictionary<XName, int> Order_tblPr = new Dictionary<XName, int>
+        private static readonly Dictionary<XName, int> Order_tblPr = new Dictionary<XName, int>
         {
             { W.tblStyle, 10 },
             { W.tblpPr, 20 },
@@ -1257,10 +1389,10 @@ listSeparator
             { W.tblCellMar, 140 },
             { W.tblLook, 150 },
             { W.tblCaption, 160 },
-            { W.tblDescription, 170 },
+            { W.tblDescription, 170 }
         };
 
-        private static Dictionary<XName, int> Order_tblBorders = new Dictionary<XName, int>
+        private static readonly Dictionary<XName, int> Order_tblBorders = new Dictionary<XName, int>
         {
             { W.top, 10 },
             { W.left, 20 },
@@ -1272,7 +1404,7 @@ listSeparator
             { W.insideV, 80 },
         };
 
-        private static Dictionary<XName, int> Order_tcPr = new Dictionary<XName, int>
+        private static readonly Dictionary<XName, int> Order_tcPr = new Dictionary<XName, int>
         {
             { W.cnfStyle, 10 },
             { W.tcW, 20 },
@@ -1287,10 +1419,10 @@ listSeparator
             { W.tcFitText, 110 },
             { W.vAlign, 120 },
             { W.hideMark, 130 },
-            { W.headers, 140 },
+            { W.headers, 140 }
         };
 
-        private static Dictionary<XName, int> Order_tcBorders = new Dictionary<XName, int>
+        private static readonly Dictionary<XName, int> Order_tcBorders = new Dictionary<XName, int>
         {
             { W.top, 10 },
             { W.start, 20 },
@@ -1301,10 +1433,10 @@ listSeparator
             { W.insideH, 70 },
             { W.insideV, 80 },
             { W.tl2br, 90 },
-            { W.tr2bl, 100 },
+            { W.tr2bl, 100 }
         };
 
-        private static Dictionary<XName, int> Order_pBdr = new Dictionary<XName, int>
+        private static readonly Dictionary<XName, int> Order_pBdr = new Dictionary<XName, int>
         {
             { W.top, 10 },
             { W.left, 20 },
@@ -1316,7 +1448,7 @@ listSeparator
 
         public static object WmlOrderElementsPerStandard(XNode node)
         {
-            XElement element = node as XElement;
+            var element = node as XElement;
             if (element != null)
             {
                 if (element.Name == W.pPr)
@@ -1326,6 +1458,7 @@ listSeparator
                         {
                             if (Order_pPr.ContainsKey(e.Name))
                                 return Order_pPr[e.Name];
+
                             return 999;
                         }));
 
@@ -1336,6 +1469,7 @@ listSeparator
                         {
                             if (Order_rPr.ContainsKey(e.Name))
                                 return Order_rPr[e.Name];
+
                             return 999;
                         }));
 
@@ -1346,6 +1480,7 @@ listSeparator
                         {
                             if (Order_tblPr.ContainsKey(e.Name))
                                 return Order_tblPr[e.Name];
+
                             return 999;
                         }));
 
@@ -1356,6 +1491,7 @@ listSeparator
                         {
                             if (Order_tcPr.ContainsKey(e.Name))
                                 return Order_tcPr[e.Name];
+
                             return 999;
                         }));
 
@@ -1366,6 +1502,7 @@ listSeparator
                         {
                             if (Order_tcBorders.ContainsKey(e.Name))
                                 return Order_tcBorders[e.Name];
+
                             return 999;
                         }));
 
@@ -1376,6 +1513,7 @@ listSeparator
                         {
                             if (Order_tblBorders.ContainsKey(e.Name))
                                 return Order_tblBorders[e.Name];
+
                             return 999;
                         }));
 
@@ -1411,6 +1549,7 @@ listSeparator
                         {
                             if (Order_settings.ContainsKey(e.Name))
                                 return Order_settings[e.Name];
+
                             return 999;
                         }));
 
@@ -1418,21 +1557,22 @@ listSeparator
                     element.Attributes(),
                     element.Nodes().Select(n => WmlOrderElementsPerStandard(n)));
             }
+
             return node;
         }
 
         public static WmlDocument BreakLinkToTemplate(WmlDocument source)
         {
-            using (MemoryStream ms = new MemoryStream())
+            using (var ms = new MemoryStream())
             {
                 ms.Write(source.DocumentByteArray, 0, source.DocumentByteArray.Length);
                 using (WordprocessingDocument wDoc = WordprocessingDocument.Open(ms, true))
                 {
-                    var efpp = wDoc.ExtendedFilePropertiesPart;
+                    ExtendedFilePropertiesPart efpp = wDoc.ExtendedFilePropertiesPart;
                     if (efpp != null)
                     {
-                        var xd = efpp.GetXDocument();
-                        var template = xd.Descendants(EP.Template).FirstOrDefault();
+                        XDocument xd = efpp.GetXDocument();
+                        XElement template = xd.Descendants(EP.Template).FirstOrDefault();
                         if (template != null)
                             template.Value = "";
                         efpp.PutXDocument();
@@ -4192,7 +4332,11 @@ listSeparator
         public static readonly XNamespace plegacy = "urn:schemas-microsoft-com:office:powerpoint";
         public static readonly XName textdata = plegacy + "textdata";
     }
-
+    public static class SVG
+    {
+        public static readonly XNamespace svg = "http://schemas.microsoft.com/office/drawing/2016/SVG/main";
+        public static readonly XName svgBlip = svg + "svgBlip";
+    }
     public static class R
     {
         public static readonly XNamespace r =
@@ -5797,6 +5941,9 @@ listSeparator
     {
         public static readonly XNamespace xsi =
             "http://www.w3.org/2001/XMLSchema-instance";
+
+        public static readonly XName schemaLocation = xsi + "schemaLocation";
+        public static readonly XName noNamespaceSchemaLocation = xsi + "noNamespaceSchemaLocation";
         public static readonly XName type = xsi + "type";
     }
 
@@ -5805,40 +5952,44 @@ listSeparator
 
     public static class PtOpenXml
     {
-        public static XNamespace ptOpenXml = "http://powertools.codeplex.com/documentbuilder/2011/insert";
-        public static XName Insert = ptOpenXml + "Insert";
-        public static XName Id = "Id";
-
-        public static XNamespace pt = "http://powertools.codeplex.com/2011";
-        public static XName Uri = pt + "Uri";
-        public static XName Unid = pt + "Unid";
-        public static XName SHA1Hash = pt + "SHA1Hash";
-        public static XName CorrelatedSHA1Hash = pt + "CorrelatedSHA1Hash";
-        public static XName StructureSHA1Hash = pt + "StructureSHA1Hash";
-        public static XName CorrelationSet = pt + "CorrelationSet";
-        public static XName Status = pt + "Status";
-
-        public static XName Level = pt + "Level";
-        public static XName IndentLevel = pt + "IndentLevel";
-        public static XName ContentType = pt + "ContentType";
-
-        public static XName trPr = pt + "trPr";
-        public static XName tcPr = pt + "tcPr";
-        public static XName rPr = pt + "rPr";
-        public static XName pPr = pt + "pPr";
-        public static XName tblPr = pt + "tblPr";
-        public static XName style = pt + "style";
-
-        public static XName FontName = pt + "FontName";
-        public static XName LanguageType = pt + "LanguageType";
-        public static XName AbstractNumId = pt + "AbstractNumId";
-        public static XName StyleName = pt + "StyleName";
-        public static XName TabWidth = pt + "TabWidth";
-        public static XName Leader = pt + "Leader";
-
-        public static XName ListItemRun = pt + "ListItemRun";
-
-        public static XName HtmlToWmlCssWidth = pt + "HtmlToWmlCssWidth";
+        public static readonly XNamespace ptOpenXml = "http://powertools.codeplex.com/documentbuilder/2011/insert";
+        public static readonly XName Insert = ptOpenXml + "Insert";
+        public static readonly XName Id = "Id";
+
+        public static readonly XNamespace pt = "http://powertools.codeplex.com/2011";
+        public static readonly XName Uri = pt + "Uri";
+        public static readonly XName Unid = pt + "Unid";
+        public static readonly XName SHA1Hash = pt + "SHA1Hash";
+        public static readonly XName CorrelatedSHA1Hash = pt + "CorrelatedSHA1Hash";
+        public static readonly XName StructureSHA1Hash = pt + "StructureSHA1Hash";
+        public static readonly XName CorrelationSet = pt + "CorrelationSet";
+        public static readonly XName Status = pt + "Status";
+
+        public static readonly XName Level = pt + "Level";
+        public static readonly XName IndentLevel = pt + "IndentLevel";
+        public static readonly XName ContentType = pt + "ContentType";
+
+        public static readonly XName trPr = pt + "trPr";
+        public static readonly XName tcPr = pt + "tcPr";
+        public static readonly XName rPr = pt + "rPr";
+        public static readonly XName pPr = pt + "pPr";
+        public static readonly XName tblPr = pt + "tblPr";
+        public static readonly XName style = pt + "style";
+
+        public static readonly XName instrText = pt + W.instrText.LocalName;
+
+        public static readonly XName FontName = pt + "FontName";
+        public static readonly XName LanguageType = pt + "LanguageType";
+        public static readonly XName AbstractNumId = pt + "AbstractNumId";
+        public static readonly XName HtmlStructure = pt + "HtmlStructure";
+        public static readonly XName HtmlStyle = pt + "HtmlStyle";
+        public static readonly XName StyleName = pt + "StyleName";
+        public static readonly XName TabWidth = pt + "TabWidth";
+        public static readonly XName Leader = pt + "Leader";
+
+        public static readonly XName ListItemRun = pt + "ListItemRun";
+
+        public static readonly XName HtmlToWmlCssWidth = pt + "HtmlToWmlCssWidth";
     }
 
     public static class Xhtml

+ 239 - 26
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/PtUtil.cs

@@ -8,6 +8,7 @@ using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Linq;
+using System.Security.Cryptography;
 using System.Text;
 using System.Threading.Tasks;
 using System.Xml;
@@ -18,6 +19,32 @@ namespace OpenXmlPowerTools
 {
     public static class PtUtils
     {
+        public static string SHA1HashStringForUTF8String(string s)
+        {
+            byte[] bytes = Encoding.UTF8.GetBytes(s);
+            var sha1 = SHA1.Create();
+            byte[] hashBytes = sha1.ComputeHash(bytes);
+            return HexStringFromBytes(hashBytes);
+        }
+
+        public static string SHA1HashStringForByteArray(byte[] bytes)
+        {
+            var sha1 = SHA1.Create();
+            byte[] hashBytes = sha1.ComputeHash(bytes);
+            return HexStringFromBytes(hashBytes);
+        }
+
+        public static string HexStringFromBytes(byte[] bytes)
+        {
+            var sb = new StringBuilder();
+            foreach (byte b in bytes)
+            {
+                var hex = b.ToString("x2");
+                sb.Append(hex);
+            }
+            return sb.ToString();
+        }
+
         public static string NormalizeDirName(string dirName)
         {
             string d = dirName.Replace('\\', '/');
@@ -253,8 +280,8 @@ namespace OpenXmlPowerTools
         {
             return element.Attributes()
                     .Where(a => !a.IsNamespaceDeclaration &&
-                        a.Name != Xsi.schemaLocation &&
-                        a.Name != Xsi.noNamespaceSchemaLocation)
+                        a.Name != XSI.schemaLocation &&
+                        a.Name != XSI.noNamespaceSchemaLocation)
                     .OrderBy(a => a.Name.NamespaceName)
                     .ThenBy(a => a.Name.LocalName)
                     .Select(
@@ -770,8 +797,7 @@ namespace OpenXmlPowerTools
             while (i < source.Length)
                 yield return source[i++];
         }
-
-        public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count)
+        public static IEnumerable<T> PtSkipLast<T>(this IEnumerable<T> source, int count)
         {
             var saveList = new Queue<T>();
             var saved = 0;
@@ -788,7 +814,6 @@ namespace OpenXmlPowerTools
                 yield return saveList.Dequeue();
             }
         }
-
         public static bool? ToBoolean(this XAttribute a)
         {
             if (a == null)
@@ -1050,6 +1075,55 @@ namespace OpenXmlPowerTools
                 return null;
             }
         }
+
+        /// <summary>
+        /// Gets or creates the given container's first child element having the given
+        /// <see cref="XName"/>.
+        /// </summary>
+        /// <param name="container">The container <see cref="XElement"/>.</param>
+        /// <param name="childName">The child element's <see cref="XName"/>.</param>
+        /// <returns>The container's first child <see cref="XElement"/>.</returns>
+        public static XElement GetOrCreateFirstChild(this XElement container, XName childName)
+        {
+            if (container == null) throw new ArgumentNullException(nameof(container));
+            if (childName == null) throw new ArgumentNullException(nameof(childName));
+
+            XElement child = container.Element(childName);
+            if (child == null)
+            {
+                child = new XElement(childName);
+                container.AddFirst(child);
+            }
+
+            return child;
+        }
+
+        /// <summary>
+        /// Gets the given element's parent element or throws an <see cref="ArgumentException"/>
+        /// in case the element does not have a parent.
+        /// </summary>
+        /// <param name="element">The element.</param>
+        /// <returns>The element's parent.</returns>
+        public static XElement GetParent(this XElement element)
+        {
+            if (element == null) throw new ArgumentNullException(nameof(element));
+
+            return element.Parent ?? throw new ArgumentException("Element does not have a parent.");
+        }
+
+        /// <summary>
+        /// Moves the given element to a new parent.
+        /// </summary>
+        /// <param name="element">The element.</param>
+        /// <param name="parent">The new parent.</param>
+        public static void MoveTo(this XElement element, XElement parent)
+        {
+            if (element == null) throw new ArgumentNullException(nameof(element));
+            if (parent == null) throw new ArgumentNullException(nameof(parent));
+
+            element.Remove();
+            parent.Add(element);
+        }
     }
 
     public class ExecutableRunner
@@ -1143,42 +1217,174 @@ namespace OpenXmlPowerTools
         }
     }
 
-    public static class PtBucketTimer
+    public class BucketTimer
     {
+        public BucketTimer()
+        {
+            Buckets = new Dictionary<string, BucketInfo>();
+        }
+
         private class BucketInfo
         {
             public int Count;
             public TimeSpan Time;
         }
 
-        private static string LastBucket = null;
-        private static DateTime LastTime;
-        private static Dictionary<string, BucketInfo> Buckets;
+        private string LastBucket = null;
+        private DateTime LastTime;
+        private Dictionary<string, BucketInfo> Buckets;
 
-        public static void Bucket(string bucket)
+        public void Bucket(string bucket)
         {
             DateTime now = DateTime.Now;
             if (LastBucket != null)
+                AddToBuckets(now);
+            LastBucket = bucket;
+            LastTime = now;
+        }
+
+        public void End()
+        {
+            DateTime now = DateTime.Now;
+            if (LastBucket != null)
+                AddToBuckets(now);
+            LastBucket = null;
+        }
+
+        private void AddToBuckets(DateTime now)
+        {
+            TimeSpan d = now - LastTime;
+            var bucketParts = LastBucket.Split('/');
+            var bucketList = bucketParts.Select((t, i) => bucketParts
+                .Take(i + 1)
+                .Select(z => z + "/")
+                .StringConcatenate()
+                .Trim('/'))
+                .ToList();
+
+            foreach (var b in bucketList)
             {
-                TimeSpan d = now - LastTime;
-                if (Buckets.ContainsKey(LastBucket))
+                if (Buckets.ContainsKey(b))
                 {
-                    Buckets[LastBucket].Count = Buckets[LastBucket].Count + 1;
-                    Buckets[LastBucket].Time += d;
+                    Buckets[b].Count = Buckets[b].Count + 1;
+                    Buckets[b].Time += d;
                 }
                 else
                 {
-                    Buckets.Add(LastBucket, new BucketInfo()
+                    Buckets.Add(b, new BucketInfo()
                     {
                         Count = 1,
                         Time = d,
                     });
                 }
             }
+            LastTime = now;
+        }
+
+        public string DumpBucketsByKey()
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (var bucket in Buckets.OrderBy(b => b.Key))
+            {
+                string ts = bucket.Value.Time.ToString();
+                if (ts.Contains('.'))
+                    ts = ts.Substring(0, ts.Length - 5);
+                string s = bucket.Key.PadRight(60, '-') + "  " + string.Format("{0:00000000}", bucket.Value.Count) + "  " + ts;
+                sb.Append(s + Environment.NewLine);
+            }
+            TimeSpan total = Buckets
+                .Aggregate(TimeSpan.Zero, (t, b) => t + b.Value.Time);
+            var tz = total.ToString();
+            sb.Append(string.Format("Total: {0}", tz.Substring(0, tz.Length - 5)));
+            return sb.ToString();
+        }
+
+        public string DumpBucketsToCsvByKey()
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (var bucket in Buckets.OrderBy(b => b.Key))
+            {
+                string ts = bucket.Value.Time.ToString();
+                if (ts.Contains('.'))
+                    ts = ts.Substring(0, ts.Length - 5);
+                string s = bucket.Key + "," + bucket.Value.Count.ToString() + "," + ts;
+                sb.Append(s + Environment.NewLine);
+            }
+            return sb.ToString();
+        }
+
+        public string DumpBucketsByTime()
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (var bucket in Buckets.OrderBy(b => b.Value.Time))
+            {
+                string ts = bucket.Value.Time.ToString();
+                if (ts.Contains('.'))
+                    ts = ts.Substring(0, ts.Length - 5);
+                string s = bucket.Key.PadRight(60, '-') + "  " + string.Format("{0:00000000}", bucket.Value.Count) + "  " + ts;
+                sb.Append(s + Environment.NewLine);
+            }
+            TimeSpan total = Buckets
+                .Aggregate(TimeSpan.Zero, (t, b) => t + b.Value.Time);
+            var tz = total.ToString();
+            sb.Append(string.Format("Total: {0}", tz.Substring(0, tz.Length - 5)));
+            return sb.ToString();
+        }
+
+        public void Init()
+        {
+            Buckets = new Dictionary<string, BucketInfo>();
+        }
+    }
+    public static class PtBucketTimer
+    {
+        private class BucketInfo
+        {
+            public int Count;
+            public TimeSpan Time;
+        }
+
+        public static string LastBucket = null;
+        private static DateTime LastTime;
+        private static Dictionary<string, BucketInfo> Buckets;
+
+        public static void Bucket(string bucket)
+        {
+            DateTime now = DateTime.Now;
+            if (LastBucket != null)
+                AddToBuckets(now);
             LastBucket = bucket;
             LastTime = now;
         }
 
+        public static void End()
+        {
+            DateTime now = DateTime.Now;
+            if (LastBucket != null)
+                AddToBuckets(now);
+            LastBucket = null;
+        }
+
+        private static void AddToBuckets(DateTime now)
+        {
+            TimeSpan d = now - LastTime;
+
+            if (Buckets.ContainsKey(LastBucket))
+            {
+                Buckets[LastBucket].Count += 1;
+                Buckets[LastBucket].Time += d;
+            }
+            else
+            {
+                Buckets.Add(LastBucket, new BucketInfo()
+                {
+                    Count = 1,
+                    Time = d,
+                });
+            }
+            LastTime = now;
+        }
+
         public static string DumpBucketsByKey()
         {
             StringBuilder sb = new StringBuilder();
@@ -1187,7 +1393,7 @@ namespace OpenXmlPowerTools
                 string ts = bucket.Value.Time.ToString();
                 if (ts.Contains('.'))
                     ts = ts.Substring(0, ts.Length - 5);
-                string s = bucket.Key.PadRight(60, '-') + "  " + string.Format("{0:00000000}", bucket.Value.Count) + "  " + ts;
+                string s = bucket.Key.PadRight(80, '-') + "  " + string.Format("{0:00000000}", bucket.Value.Count) + "  " + ts;
                 sb.Append(s + Environment.NewLine);
             }
             TimeSpan total = Buckets
@@ -1197,6 +1403,20 @@ namespace OpenXmlPowerTools
             return sb.ToString();
         }
 
+        public static string DumpBucketsToCsvByKey()
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (var bucket in Buckets.OrderBy(b => b.Key))
+            {
+                string ts = bucket.Value.Time.TotalMilliseconds.ToString();
+                if (ts.Contains('.'))
+                    ts = ts.Substring(0, ts.Length - 5);
+                string s = bucket.Key + "," + bucket.Value.Count.ToString() + "," + ts;
+                sb.Append(s + Environment.NewLine);
+            }
+            return sb.ToString();
+        }
+
         public static string DumpBucketsByTime()
         {
             StringBuilder sb = new StringBuilder();
@@ -1205,7 +1425,7 @@ namespace OpenXmlPowerTools
                 string ts = bucket.Value.Time.ToString();
                 if (ts.Contains('.'))
                     ts = ts.Substring(0, ts.Length - 5);
-                string s = bucket.Key.PadRight(60, '-') + "  " + string.Format("{0:00000000}", bucket.Value.Count) + "  " + ts;
+                string s = bucket.Key.PadRight(80, '-') + "  " + string.Format("{0:00000000}", bucket.Value.Count) + "  " + ts;
                 sb.Append(s + Environment.NewLine);
             }
             TimeSpan total = Buckets
@@ -1217,10 +1437,10 @@ namespace OpenXmlPowerTools
 
         public static void Init()
         {
+            LastBucket = null;
             Buckets = new Dictionary<string, BucketInfo>();
         }
     }
-
     public class XEntity : XText
     {
         public override void WriteTo(XmlWriter writer)
@@ -1238,12 +1458,5 @@ namespace OpenXmlPowerTools
         {
         }
     }
-
-    public static class Xsi
-    {
-        public static XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
-
-        public static XName schemaLocation = xsi + "schemaLocation";
-        public static XName noNamespaceSchemaLocation = xsi + "noNamespaceSchemaLocation";
-    }
+ 
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1147 - 912
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/RevisionProcessor.cs


+ 33 - 24
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/TestUtil.cs

@@ -2,66 +2,75 @@
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 using System;
-using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace OpenXmlPowerTools
 {
-    public class TestUtil
+    public static class TestUtil
     {
-        private static bool? s_DeleteTempFiles = null;
+        public static readonly DirectoryInfo SourceDir = new DirectoryInfo("../../../../TestFiles/");
+
+        private static bool? _deleteTempFiles;
+
+        private static DirectoryInfo _tempDir;
+
 
         public static bool DeleteTempFiles
         {
             get
             {
-                if (s_DeleteTempFiles != null)
-                    return (bool)s_DeleteTempFiles;
-                FileInfo donotdelete = new FileInfo("donotdelete.txt");
-                s_DeleteTempFiles = !donotdelete.Exists;
-                return (bool)s_DeleteTempFiles;
+                if (_deleteTempFiles != null) return (bool)_deleteTempFiles;
+
+                var donotdelete = new FileInfo("donotdelete.txt");
+                _deleteTempFiles = !donotdelete.Exists;
+
+                return (bool)_deleteTempFiles;
             }
         }
 
-        private static DirectoryInfo s_TempDir = null;
         public static DirectoryInfo TempDir
         {
             get
             {
-                if (s_TempDir != null)
-                    return s_TempDir;
-                else
-                {
-                    var now = DateTime.Now;
-                    var tempDirName = String.Format("Test-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", now.Year - 2000, now.Month, now.Day, now.Hour, now.Minute, now.Second);
-                    s_TempDir = new DirectoryInfo(Path.Combine(".", tempDirName));
-                    s_TempDir.Create();
-                    return s_TempDir;
-                }
+                if (_tempDir != null) return _tempDir;
+
+                DateTime now = DateTime.Now;
+                string tempDirName =
+                    $"Test-{now.Year - 2000:00}-{now.Month:00}-{now.Day:00}-{now.Hour:00}{now.Minute:00}{now.Second:00}";
+
+                _tempDir = new DirectoryInfo(Path.Combine(".", tempDirName));
+                _tempDir.Create();
+
+                return _tempDir;
             }
         }
 
         public static void NotePad(string str)
         {
-            var guidName = Guid.NewGuid().ToString().Replace("-", "") + ".txt";
+            string guidName = Guid.NewGuid().ToString().Replace("-", "") + ".txt";
             var fi = new FileInfo(Path.Combine(TempDir.FullName, guidName));
             File.WriteAllText(fi.FullName, str);
+
             var notepadExe = new FileInfo(@"C:\Program Files (x86)\Notepad++\notepad++.exe");
             if (!notepadExe.Exists)
+            {
                 notepadExe = new FileInfo(@"C:\Program Files\Notepad++\notepad++.exe");
+            }
+
             if (!notepadExe.Exists)
+            {
                 notepadExe = new FileInfo(@"C:\Windows\System32\notepad.exe");
+            }
+
             ExecutableRunner.RunExecutable(notepadExe.FullName, fi.FullName, TempDir.FullName);
         }
 
         public static void KDiff3(FileInfo oldFi, FileInfo newFi)
         {
             var kdiffExe = new FileInfo(@"C:\Program Files (x86)\KDiff3\kdiff3.exe");
-            var result = ExecutableRunner.RunExecutable(kdiffExe.FullName, oldFi.FullName + " " + newFi.FullName, TempDir.FullName);
+            ExecutableRunner.RunResults unused =
+                ExecutableRunner.RunExecutable(kdiffExe.FullName, oldFi.FullName + " " + newFi.FullName, TempDir.FullName);
         }
 
         public static void Explorer(DirectoryInfo di)

+ 5 - 9
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/UnicodeMapper.cs

@@ -3,11 +3,7 @@
 
 /***************************************************************************
 
-Copyright (c) Microsoft Corporation 2016.
-
-This code is licensed using the Microsoft Public License (Ms-PL).  The text of the license can be found here:
-
-http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx
+Copyright (c) Thomas Barnekow 2016.
 
 Developer: Thomas Barnekow
 Email: thomas@barnekow.info
@@ -69,7 +65,7 @@ namespace OpenXmlPowerTools
 
             // For w:t elements, we obviously want the element's value.
             if (element.Name == W.t)
-                return (string) element;
+                return (string)element;
 
             // Turn elements representing special characters into their corresponding
             // unicode characters.
@@ -141,7 +137,7 @@ namespace OpenXmlPowerTools
         /// <returns>The Unicode character used to represent the symbol.</returns>
         public static char SymToChar(string fontAttributeValue, char unicodeValue)
         {
-            return SymToChar(fontAttributeValue, (int) unicodeValue);
+            return SymToChar(fontAttributeValue, (int)unicodeValue);
         }
 
         /// <summary>
@@ -233,7 +229,7 @@ namespace OpenXmlPowerTools
             // Use the actual Unicode value if it has not yet been used with another font.
             // Otherwise, create a special Unicode value in the private use area to represent
             // the current w:sym element.
-            var unicodeChar = (char) Convert.ToInt32(charAttributeValue, 16);
+            var unicodeChar = (char)Convert.ToInt32(charAttributeValue, 16);
             if (UnicodeCharToSymDictionary.ContainsKey(unicodeChar))
                 unicodeChar = ++_lastUnicodeChar;
 
@@ -255,7 +251,7 @@ namespace OpenXmlPowerTools
                 .Select(CharToRunChild)
                 .GroupAdjacent(e => e.Name == W.t)
                 .SelectMany(grouping => grouping.Key
-                    ? StringToSingleRunList(grouping.Select(t => (string) t).StringConcatenate(), runProperties)
+                    ? StringToSingleRunList(grouping.Select(t => (string)t).StringConcatenate(), runProperties)
                     : grouping.Select(e => new XElement(W.r, runProperties, e)))
                 .ToList();
         }

+ 2 - 2
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/WORDHelper.cs

@@ -367,8 +367,8 @@ namespace HTEXLib.DOCX.OpenXmlTool
         public static HtexPattFill DoPattFill(DocumentFormat.OpenXml.Drawing.PatternFill patternFill, WordprocessingDocument wordDoc)
         {
             HtexPattFill htexPattFill = new HtexPattFill();
-            Color FgClr;
-            Color BgClr;
+            Color FgClr = Color.Empty;
+            Color BgClr = Color.Empty;
             if (patternFill.ForegroundColor != null)
             {
                 var fgClr = ColorTypeColors(patternFill.ForegroundColor,wordDoc);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 373 - 155
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/Properties/WmlComparer.cs


+ 22 - 21
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/WmlToHtmlConverter.cs

@@ -71,7 +71,7 @@ namespace OpenXmlPowerTools
             CssClassPrefix = "pt-";
             TableInnerCss = true;
             FabricateCssClasses = true;
-            GeneralCss = "span {/* white-space: pre-wrap;*/ }";
+            GeneralCss = "span { white-space: pre-wrap; }";
             AdditionalCss = "";
             RestrictToSupportedLanguages = false;
             RestrictToSupportedNumberingFormats = false;
@@ -113,7 +113,7 @@ namespace OpenXmlPowerTools
             PageTitle = "";
             CssClassPrefix = "pt-";
             FabricateCssClasses = true;
-            GeneralCss = "span { /*white-space: pre-wrap;*/ }";
+            GeneralCss = "span { white-space: pre-wrap; }";
             AdditionalCss = "";
             RestrictToSupportedLanguages = false;
             RestrictToSupportedNumberingFormats = false;
@@ -2704,7 +2704,8 @@ namespace OpenXmlPowerTools
 
             // w:defaultTabStop in settings
             var sxd = wordDoc.MainDocumentPart.DocumentSettingsPart.GetXDocument();
-            var defaultTabStop = (int?)sxd.Descendants(W.defaultTabStop).Attributes(W.val).FirstOrDefault() ?? 720;
+            var defaultTabStopValue = (string)sxd.Descendants(W.defaultTabStop).Attributes(W.val).FirstOrDefault();
+            var defaultTabStop = defaultTabStopValue != null ? WordprocessingMLUtil.StringToTwips(defaultTabStopValue) : 720;
 
             var pxd = wordDoc.MainDocumentPart.GetXDocument();
             var root = pxd.Root;
@@ -2743,16 +2744,16 @@ namespace OpenXmlPowerTools
             {
                 // todo need to handle start and end attributes
 
-                var left = (int?)ind.Attribute(W.left);
+                var left = WordprocessingMLUtil.AttributeToTwips(ind.Attribute(W.left));
                 if (left != null)
                     leftInTwips = (int)left;
 
                 var firstLine = 0;
-                var firstLineAtt = (int?)ind.Attribute(W.firstLine);
+                var firstLineAtt = WordprocessingMLUtil.AttributeToTwips(ind.Attribute(W.firstLine));
                 if (firstLineAtt != null)
                     firstLine = (int)firstLineAtt;
 
-                var hangingAtt = (int?)ind.Attribute(W.hanging);
+                var hangingAtt = WordprocessingMLUtil.AttributeToTwips(ind.Attribute(W.hanging));
                 if (hangingAtt != null)
                     firstLine = -(int)hangingAtt;
 
@@ -2826,7 +2827,7 @@ namespace OpenXmlPowerTools
 
                     var tabAfterText = tabs
                         .Elements(W.tab)
-                        .FirstOrDefault(t => (int)t.Attribute(W.pos) > testAmount);
+                        .FirstOrDefault(t => WordprocessingMLUtil.StringToTwips((string)t.Attribute(W.pos)) > testAmount);
 
                     if (tabAfterText == null)
                     {
@@ -2862,14 +2863,14 @@ namespace OpenXmlPowerTools
                             new XElement(W.t, textAfterTab));
 
                         var widthOfTextAfterTab = CalcWidthOfRunInTwips(dummyRun2);
-                        var delta2 = (int)tabAfterText.Attribute(W.pos) - widthOfTextAfterTab - twipCounter;
+                        var delta2 = WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)) - widthOfTextAfterTab - twipCounter;
                         if (delta2 < 0)
                             delta2 = 0;
                         currentElement.Add(
                             new XAttribute(PtOpenXml.TabWidth,
                                 string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}", (decimal)delta2 / 1440m)),
                             GetLeader(tabAfterText));
-                        twipCounter = Math.Max((int)tabAfterText.Attribute(W.pos), twipCounter + widthOfTextAfterTab);
+                        twipCounter = Math.Max(WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)), twipCounter + widthOfTextAfterTab);
 
                         var lastElement = textElementsToMeasure.LastOrDefault();
                         if (lastElement == null)
@@ -2909,7 +2910,7 @@ namespace OpenXmlPowerTools
                                 new XElement(W.t, mantissa));
 
                             var widthOfMantissa = CalcWidthOfRunInTwips(dummyRun4);
-                            var delta2 = (int)tabAfterText.Attribute(W.pos) - widthOfMantissa - twipCounter;
+                            var delta2 = WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)) - widthOfMantissa - twipCounter;
                             if (delta2 < 0)
                                 delta2 = 0;
                             currentElement.Add(
@@ -2924,7 +2925,7 @@ namespace OpenXmlPowerTools
                                 new XElement(W.t, decims));
 
                             var widthOfDecims = CalcWidthOfRunInTwips(dummyRun4);
-                            twipCounter = Math.Max((int)tabAfterText.Attribute(W.pos) + widthOfDecims, twipCounter + widthOfMantissa + widthOfDecims);
+                            twipCounter = Math.Max(WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)) + widthOfDecims, twipCounter + widthOfMantissa + widthOfDecims);
 
                             var lastElement = textElementsToMeasure.LastOrDefault();
                             if (lastElement == null)
@@ -2944,15 +2945,15 @@ namespace OpenXmlPowerTools
                                 new XElement(W.t, textAfterTab));
 
                             var widthOfTextAfterTab = CalcWidthOfRunInTwips(dummyRun2);
-                            var delta2 = (int)tabAfterText.Attribute(W.pos) - widthOfTextAfterTab - twipCounter;
+                            var delta2 = WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)) - widthOfTextAfterTab - twipCounter;
                             if (delta2 < 0)
                                 delta2 = 0;
                             currentElement.Add(
                                 new XAttribute(PtOpenXml.TabWidth,
                                     string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}", (decimal)delta2 / 1440m)),
                                 GetLeader(tabAfterText));
-                            twipCounter = Math.Max((int)tabAfterText.Attribute(W.pos), twipCounter + widthOfTextAfterTab);
-
+                            twipCounter = Math.Max(WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)), twipCounter + widthOfTextAfterTab);
+                            
                             var lastElement = textElementsToMeasure.LastOrDefault();
                             if (lastElement == null)
                                 break; // we're done
@@ -2988,14 +2989,14 @@ namespace OpenXmlPowerTools
                             new XElement(W.t, textAfterTab));
 
                         var widthOfText = CalcWidthOfRunInTwips(dummyRun4);
-                        var delta2 = (int)tabAfterText.Attribute(W.pos) - (widthOfText / 2) - twipCounter;
+                        var delta2 = WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)) - (widthOfText / 2) - twipCounter;
                         if (delta2 < 0)
                             delta2 = 0;
                         currentElement.Add(
                             new XAttribute(PtOpenXml.TabWidth,
                                 string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}", (decimal)delta2 / 1440m)),
                             GetLeader(tabAfterText));
-                        twipCounter = Math.Max((int)tabAfterText.Attribute(W.pos) + widthOfText / 2, twipCounter + widthOfText);
+                        twipCounter = Math.Max(WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)) + widthOfText / 2, twipCounter + widthOfText);
 
                         var lastElement = textElementsToMeasure.LastOrDefault();
                         if (lastElement == null)
@@ -3009,12 +3010,12 @@ namespace OpenXmlPowerTools
                     }
                     if (tabVal == "left" || tabVal == "start" || tabVal == "num")
                     {
-                        var delta = (int)tabAfterText.Attribute(W.pos) - twipCounter;
+                        var delta = WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos)) - twipCounter;
                         currentElement.Add(
                             new XAttribute(PtOpenXml.TabWidth,
                                 string.Format(NumberFormatInfo.InvariantInfo, "{0:0.000}", (decimal)delta / 1440m)),
                             GetLeader(tabAfterText));
-                        twipCounter = (int)tabAfterText.Attribute(W.pos);
+                        twipCounter = WordprocessingMLUtil.StringToTwips((string)tabAfterText.Attribute(W.pos));
 
                         currentElementIdx++;
                         if (currentElementIdx >= contentToMeasure.Length)
@@ -3076,13 +3077,13 @@ namespace OpenXmlPowerTools
             var lastTabElement = tabs
                 .Elements(W.tab)
                 .Where(t => (string)t.Attribute(W.val) != "clear" && (string)t.Attribute(W.val) != "bar")
-                .OrderBy(t => (int)t.Attribute(W.pos))
+                .OrderBy(t => WordprocessingMLUtil.StringToTwips((string)t.Attribute(W.pos)))
                 .LastOrDefault();
             if (lastTabElement != null)
             {
                 if (defaultTabStop == 0)
                     defaultTabStop = 720;
-                var rangeStart = (int)lastTabElement.Attribute(W.pos) / defaultTabStop + 1;
+                var rangeStart = WordprocessingMLUtil.StringToTwips((string)lastTabElement.Attribute(W.pos)) / defaultTabStop + 1;
                 var tempTabs = new XElement(W.tabs,
                     tabs.Elements().Where(t => (string)t.Attribute(W.val) != "clear" && (string)t.Attribute(W.val) != "bar"),
                     Enumerable.Range(rangeStart, 100)
@@ -3090,7 +3091,7 @@ namespace OpenXmlPowerTools
                         new XAttribute(W.val, "left"),
                         new XAttribute(W.pos, r * defaultTabStop))));
                 tempTabs = new XElement(W.tabs,
-                    tempTabs.Elements().OrderBy(t => (int)t.Attribute(W.pos)));
+                    tempTabs.Elements().OrderBy(t => WordprocessingMLUtil.StringToTwips((string)t.Attribute(W.pos))));
                 return tempTabs;
             }
             else

+ 2 - 2
TEAMModelOS.HTEXLib/DOCX/OpenXmlTool/XlsxTables.cs

@@ -60,7 +60,7 @@ namespace OpenXmlPowerTools
             return Parent
                 .Rows()
                 .Skip(headerRowsCount)
-                .SkipLast(totalRowsCount)
+                .PtSkipLast(totalRowsCount)
                 .Where(r =>
                 {
                     int rowId = Int32.Parse(r.RowId);
@@ -366,7 +366,7 @@ namespace OpenXmlPowerTools
 
         public static IEnumerable<Row> Rows(this WorksheetPart worksheetPart)
         {
-            XNamespace s = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
+            //XNamespace s = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
             var rows = worksheetPart
                 .GetXDocument()
                 .Root

+ 0 - 5
TEAMModelOS.HTEXLib/PPTX/Controller/HtexController.cs

@@ -1,15 +1,10 @@
 using DocumentFormat.OpenXml.Presentation;
-using HTEXLib.Animations;
 using HTEXLib.Helpers.ShapeHelpers;
 using HTEXLib.Models;
 using HTEXLib.Models.HTEX;
-using Newtonsoft.Json.Linq;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Text.Json;
-using System.Text.RegularExpressions;
 
 namespace HTEXLib.Controller
 {

+ 0 - 67
TEAMModelOS.HTEXLib/PPTX/Helpers/ShapeHelpers/JsonHelper.cs

@@ -1,67 +0,0 @@
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace HTEXLib.Helpers.ShapeHelpers
-{
-   public static class JsonHelper
-    {
-        static JsonSerializerSettings settings = new JsonSerializerSettings()
-        {
-            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
-            PreserveReferencesHandling = PreserveReferencesHandling.None
-        };
-
-        /// <summary>
-        /// 使用json序列化为字符串
-        /// </summary>
-        /// <param name="dateTimeFormat">默认null,即使用json.net默认的序列化机制,如:"\/Date(1439335800000+0800)\/"</param>
-        /// <returns></returns>
-        public static string ToJson(this object input, string dateTimeFormat = "yyyy-MM-dd HH:mm:ss", bool ignoreNullValue = true, bool isIndented = false)
-        {
-            settings.NullValueHandling = ignoreNullValue ? Newtonsoft.Json.NullValueHandling.Ignore : NullValueHandling.Include;
-
-            if (!string.IsNullOrWhiteSpace(dateTimeFormat))
-            {
-                var jsonConverter = new List<JsonConverter>()
-                {
-                    new Newtonsoft.Json.Converters.IsoDateTimeConverter(){ DateTimeFormat = dateTimeFormat }//如: "yyyy-MM-dd HH:mm:ss"
-                };
-                settings.Converters = jsonConverter;
-            }
-
-            //no format
-            var format = isIndented ? Newtonsoft.Json.Formatting.Indented : Formatting.None;
-            var json = JsonConvert.SerializeObject(input, format, settings);
-            return json;
-        }
-        /// <summary>
-         /// 从序列化字符串里反序列化
-         /// </summary>
-         /// <typeparam name="T"></typeparam>
-         /// <param name="input"></param>
-         /// <param name="dateTimeFormat">默认null,即使用json.net默认的序列化机制</param>
-         /// <returns></returns>
-        public static T FromJson<T>(this string input, string dateTimeFormat = "yyyy-MM-dd HH:mm:ss", bool ignoreNullValue = true)
-        {
-            var settings = new JsonSerializerSettings()
-            {
-                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
-                PreserveReferencesHandling = PreserveReferencesHandling.Objects,
-            };
-            settings.NullValueHandling = ignoreNullValue ? Newtonsoft.Json.NullValueHandling.Ignore : NullValueHandling.Include;
-
-            if (!string.IsNullOrWhiteSpace(dateTimeFormat))
-            {
-                var jsonConverter = new List<JsonConverter>()
-                {
-                    new Newtonsoft.Json.Converters.IsoDateTimeConverter(){ DateTimeFormat = dateTimeFormat }//如: "yyyy-MM-dd HH:mm:ss"
-                };
-                settings.Converters = jsonConverter;
-            }
-
-            return JsonConvert.DeserializeObject<T>(input, settings);
-        }
-    }
-}

+ 2 - 2
TEAMModelOS.HTEXLib/PPTX/Helpers/ShapeHelpers/PPTXHelper.cs

@@ -2044,8 +2044,8 @@ namespace HTEXLib.Helpers.ShapeHelpers
         }
         public static HtexPattFill DoPattFill(DocumentFormat.OpenXml.Drawing.PatternFill patternFill , PPTSlide slide) {
             HtexPattFill htexPattFill = new HtexPattFill();
-            Color FgClr ;
-            Color BgClr ;
+            Color FgClr = Color.Empty;
+            Color BgClr = Color.Empty;
             if (patternFill.ForegroundColor != null)
             {
                 var fgClr = ColorTypeColors(patternFill.ForegroundColor, slide);

+ 2 - 7
TEAMModelOS.HTEXLib/TEAMModelOS.HTEXLib.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
+    <TargetFramework>netstandard2.1</TargetFramework>
     <Nullable>enable</Nullable>
 	<LangVersion>8.0</LangVersion>
   </PropertyGroup>
@@ -11,14 +11,9 @@
 	  <PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
 	  <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
 	  <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
-	  <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+	 
 	  <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
 	  <PackageReference Include="System.Drawing.Common" Version="8.0.6" />
 	  <PackageReference Include="System.Text.Json" Version="8.0.3" />
   </ItemGroup>
-
-  <ItemGroup>
-    <Folder Include="DOCX\OpenXmlFlatten\Contexts\" />
-  </ItemGroup>
-
 </Project>

+ 2 - 2
TEAMModelOS.HTEXLib/Translator/HTML2ITEMV2Translator.cs

@@ -28,7 +28,7 @@ namespace HTEXLib.Translator
         public string[] optionsKeys { get; set; }
         public Dictionary<string, string[]> dict { get; set; }
         public string[] Fileds { get; set; }
-        public  List<LangConfig> _langConfigs { get; set; }
+        public List<LangConfig>? _langConfigs { get; set; } = new List<LangConfig>();
         public HTML2ITEMV2Translator(string configPath)
         {
             FileStream fs = new FileStream(configPath+ "/LangConfig.json", System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
@@ -41,7 +41,7 @@ namespace HTEXLib.Translator
             }
             sr.Close();
             string text = builder.ToString();
-            _langConfigs = text.FromJson<List<LangConfig>>();
+            _langConfigs = JsonSerializer.Deserialize<List<LangConfig>>(text); 
         }
 
         /// <summary>

+ 4 - 2
TEAMModelOS.HTEXLib/Translator/HTML2ITEMV3Translator.cs

@@ -38,7 +38,7 @@ namespace HTEXLib.Translator
         public List<List<string>> optionsKeys { get; set; } = new List<List<string>>();
         public Dictionary<string, string[]> dict { get; set; }
        // public string[] Fileds { get; set; }
-        public TagConfig _TagConfig { get; set; }
+        public TagConfig? _TagConfig { get; set; }
         public HTML2ITEMV3Translator(string configPath)
         {
             FileStream fs = new FileStream(configPath+ "/LangConfigV3.json", System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
@@ -51,7 +51,9 @@ namespace HTEXLib.Translator
             }
             sr.Close();
             string text = builder.ToString();
-            _TagConfig = text.FromJson<TagConfig>();
+            _TagConfig=JsonSerializer.Deserialize<TagConfig>(text);
+
+            //_TagConfig = text.FromJson<TagConfig>();
             dict = new Dictionary<string, string[]>();
             foreach (var _langConfig in _TagConfig.LangConfig)
             {

+ 1 - 1
TEAMModelOS.SDK/Context/Attributes/Filter/ApiTokenAttribute.cs

@@ -15,9 +15,9 @@ using Microsoft.Extensions.Primitives;
 using TEAMModelOS.SDK.Models.Table;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BINormal;
 using System.Text.Json;
-using HTEXLib.COMM.Helpers;
 using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
 using System.Security.AccessControl;
+using TEAMModelOS.SDK;
 
 namespace TEAMModelOS.Filter
 {

+ 1 - 1
TEAMModelOS.SDK/DI/AzureCosmos/Inner/SQLHelper.cs

@@ -1,4 +1,4 @@
-using HTEXLib.COMM.Helpers;
+
 using Newtonsoft.Json.Linq;
 using System;
 using System.Collections;

+ 2 - 8
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs

@@ -1,10 +1,7 @@
 using System.Threading.Tasks;
 using Azure.Storage;
 using Azure.Storage.Blobs;
-using Azure.Storage.Blobs.Models;
-using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
-using TEAMModelOS.SDK.Module.AzureBlob.Container;
-using TEAMModelOS.SDK.Helper.Security.ShaHash;
+using Azure.Storage.Blobs.Models; 
 using System;
 using System.IO;
 using Azure.Storage.Blobs.Specialized;
@@ -15,15 +12,12 @@ using Azure.Core;
 using Azure;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Extension;
-using HTEXLib.COMM.Helpers;
 using System.Text.Encodings.Web;
 using TEAMModelOS.SDK.Models.Table;
 using Microsoft.AspNetCore.Http;
 using TEAMModelOS.Models;
 using Microsoft.Azure.Cosmos.Table;
-using DocumentFormat.OpenXml.Spreadsheet;
-using System.Text.Json;
-using HTEXLib.DOCX.Models;
+
 using static TEAMModelOS.SDK.CoreAPIHttpService;
 
 namespace TEAMModelOS.SDK.DI

+ 0 - 1
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs

@@ -9,7 +9,6 @@ using System.Threading.Tasks;
 using System.Linq;
 using TEAMModelOS.SDK;
 using System.Reflection;
-using HTEXLib.COMM.Helpers;
 
 namespace TEAMModelOS.SDK.DI
 {

+ 2 - 13
TEAMModelOS.SDK/DI/CoreAPI/CoreAPIHttpService.cs

@@ -1,25 +1,14 @@
-using DocumentFormat.OpenXml.Wordprocessing;
-using HTEXLib.COMM.Helpers;
-using HTEXLib.Helpers.ShapeHelpers;
-using Microsoft.AspNetCore.Hosting;
+
 using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Newtonsoft.Json;
-using OpenXmlPowerTools;
+
 using System;
 using System.Collections.Generic;
-using System.Configuration;
 using System.Dynamic;
 using System.IO;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
-using System.Net.Http.Headers;
 using System.Net.Http.Json;
-using System.Security.Policy;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;

+ 0 - 1
TEAMModelOS.SDK/DI/DingDing/DingDing.cs

@@ -12,7 +12,6 @@ using System.Text.Json;
 using System.IO;
 using TEAMModelOS.SDK.Extension;
 using System.Diagnostics;
-using HTEXLib.COMM.Helpers;
 
 namespace TEAMModelOS.SDK.DI
 {

+ 1 - 17
TEAMModelOS.SDK/DI/HttpTrigger/WebHookHttpTrigger.cs

@@ -1,33 +1,17 @@
-using Azure.Cosmos;
-using Azure.Storage.Blobs.Models;
-using HTEXLib.COMM.Helpers;
-using Microsoft.AspNetCore;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Azure.Cosmos.Table;
+ 
 using Microsoft.Azure.Functions.Worker;
 using Microsoft.Azure.Functions.Worker.Http;
-using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Linq;
 using System.Net;
 using System.Net.Http;
-using System.Net.Http.Json;
-using System.Reflection;
-using System.Security.Policy;
-using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelOS.Filter;
-using TEAMModelOS.SDK;
-using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BINormal;
-using TEAMModelOS.SDK.Models.Cosmos.Teacher;
 using TEAMModelOS.SDK.Models.Service;
-using TEAMModelOS.SDK.Models.Table;
-using static TEAMModelOS.SDK.Models.Teacher;
 
 namespace TEAMModelOS.SDK.DI
 {

+ 1 - 6
TEAMModelOS.SDK/DI/Mail/MailFactory.cs

@@ -1,18 +1,13 @@
-using DocumentFormat.OpenXml.Wordprocessing;
-using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection.Extensions;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
 using System;
 using System.Collections.Concurrent;
-using System.Collections.Generic;
 using System.ComponentModel;
-using System.Linq;
 using System.Net;
 using System.Net.Mail;
-using System.Text;
-using System.Threading.Tasks;
 using TEAMModelOS.SDK.Models;
 
 namespace TEAMModelOS.SDK.DI.Mail

+ 1 - 10
TEAMModelOS.SDK/DI/StudyAPI/ScsStudyApisService.cs

@@ -1,21 +1,12 @@
-using Azure.Cosmos;
-using HTEXLib.COMM.Helpers;
-using HTEXLib.Helpers.ShapeHelpers;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
+
 using System;
 using System.Collections.Generic;
-using System.IO;
 using System.Linq;
-using System.Net;
 using System.Net.Http;
-using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
-using TEAMModelOS.SDK.Models.Dtos;
 
 namespace TEAMModelOS.SDK.DI
 {

+ 0 - 12
TEAMModelOS.SDK/Extension/CoreTokenExtensions.cs

@@ -8,23 +8,11 @@ using Microsoft.Identity.Client;
 using System.ComponentModel;
 using System.Threading.Tasks;
 using Azure.Security.KeyVault.Secrets;
-using Azure.Core;
 using Azure.Identity;
-using System.Net.Http;
 using System.Collections.Concurrent;
-using System.Diagnostics;
-using Newtonsoft.Json;
-using System.Net;
-using Microsoft.AspNetCore.DataProtection;
 using Microsoft.Extensions.Configuration;
-using System.Configuration;
-using DocumentFormat.OpenXml.Spreadsheet;
-using System.Text.Json;
-using System.Security.Cryptography;
-using System.Reflection;
 using Microsoft.IdentityModel.Protocols.OpenIdConnect;
 using Microsoft.IdentityModel.Protocols;
-using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
 
 namespace TEAMModelOS.SDK.Extension
 {

+ 43 - 0
TEAMModelOS.SDK/Helper/Common/CollectionHelper/CollectionHelper.cs

@@ -0,0 +1,43 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    public static class CollectionHelper
+    {
+        /// <summary>
+        /// 判断集合是否为空
+        /// </summary>
+        /// <param name="collection"></param>
+        /// <returns></returns>
+        public static bool IsEmpty(this ICollection collection)
+        {
+            if (collection != null && collection.Count > 0)
+            {
+                return false;
+            }
+            else
+            {
+                return true;
+            }
+        }
+        /// <summary>
+        /// 判断集合是否不为空
+        /// </summary>
+        /// <param name="collection"></param>
+        /// <returns></returns>
+        public static bool IsNotEmpty(this ICollection collection)
+        {
+            if (collection != null && collection.Count > 0)
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+    }
+}

+ 2 - 2
TEAMModelOS.SDK/Helper/Common/ReflectorExtensions/ObjectCopyConvert.cs

@@ -1,8 +1,8 @@
-using HTEXLib.COMM.Helpers;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
 using System.Text.Json;
+using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Extension;
 
 namespace SDK.Helpers

+ 1 - 3
TEAMModelOS.SDK/Helper/Common/TaskAll/BatchTask.cs

@@ -1,8 +1,6 @@
-using HTEXLib.COMM.Helpers;
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
 using System.Threading.Tasks;
 
 namespace TEAMModelOS.SDK

+ 1 - 1
TEAMModelOS.SDK/Helper/Security/ShaHash/ShaHashHelper.cs

@@ -4,7 +4,7 @@ using System.IO;
 using System.Security.Cryptography;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Helper.Security.ShaHash
+namespace TEAMModelOS.SDK
 {
     public class ShaHashHelper
     {

+ 1 - 7
TEAMModelOS.SDK/Models/Cosmos/School/ExamImport.cs

@@ -1,11 +1,5 @@
-using DocumentFormat.OpenXml.Spreadsheet;
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
-using System.Configuration;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace TEAMModelOS.SDK.Models.Cosmos.School
 {

+ 0 - 7
TEAMModelOS.SDK/Models/Cosmos/School/ExamInfo.cs

@@ -1,12 +1,5 @@
-using DocumentFormat.OpenXml.Bibliography;
-using Newtonsoft.Json;
-using System;
 using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Text;
 using System.Text.Json;
-using System.Text.Json.Serialization;
-using TEAMModelOS.SDK.Context.Attributes.Azure;
 
 namespace TEAMModelOS.SDK.Models
 {

+ 1 - 6
TEAMModelOS.SDK/Models/Cosmos/School/IotStatistics.cs

@@ -1,9 +1,4 @@
-using DocumentFormat.OpenXml.Drawing.Charts;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
 
 namespace TEAMModelOS.SDK.Models.Cosmos.School
 {

+ 1 - 6
TEAMModelOS.SDK/Models/Cosmos/School/ScoreCalc.cs

@@ -1,9 +1,4 @@
-using DocumentFormat.OpenXml.Spreadsheet;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
 
 namespace TEAMModelOS.SDK.Models.Cosmos.School
 {

+ 7 - 10
TEAMModelOS.SDK/Models/Dtos/ItemDto.cs

@@ -1,8 +1,4 @@
-using HTEXLib;
-using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
 
 namespace TEAMModelOS.Models.Dto
 {
@@ -34,13 +30,14 @@ namespace TEAMModelOS.Models.Dto
 
 
         }
-       
-/*        public class CodeValue
-        {
-            public string code { get; set; }
-            public string value { get; set; }
-        }*/
 
+      
+
+    }
+    public class CodeValue
+    {
+        public string code { get; set; }
+        public string value { get; set; }
     }
     public class info
     {

+ 1 - 8
TEAMModelOS.SDK/Models/Dtos/LessonRecordActivityInfo.cs

@@ -1,11 +1,4 @@
-using DocumentFormat.OpenXml.EMMA;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-using TEAMModelOS.SDK.Models.Dtos;
+using System.Collections.Generic;
 
 namespace TEAMModelOS.SDK.Models.Dtos
 {

+ 1 - 2
TEAMModelOS.SDK/Models/Dtos/ShanDa/Field.cs

@@ -1,5 +1,4 @@
-using DocumentFormat.OpenXml.Office2010.ExcelAc;
-using System.Collections.Generic;
+using System.Collections.Generic;
 
 namespace TEAMModelOS.Models.ShanDa
 {

+ 0 - 1
TEAMModelOS.SDK/Models/Service/Analysis/AchievementService.cs

@@ -1,4 +1,3 @@
-using HTEXLib.COMM.Helpers;
 using System;
 using System.Collections.Generic;
 using System.Linq;

+ 0 - 0
TEAMModelOS.SDK/Models/Service/ArtService.cs


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác