From 233edb1ebb4139cced1006c920ee48e47e5750f4 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Thu, 16 Jul 2020 18:06:05 +0800 Subject: [PATCH 01/20] add table HeaderRowCount attribute --- OpenXmlPowerTools/DocumentAssembler.cs | 49 +++++++++++------- .../DocumentAssembler02/Data.xml | 17 ++++++ .../DocumentAssembler02/TemplateDocument.docx | Bin 14124 -> 17929 bytes 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/OpenXmlPowerTools/DocumentAssembler.cs b/OpenXmlPowerTools/DocumentAssembler.cs index f4d9673e..1a1f724d 100644 --- a/OpenXmlPowerTools/DocumentAssembler.cs +++ b/OpenXmlPowerTools/DocumentAssembler.cs @@ -483,6 +483,7 @@ private static string ValidatePerSchema(XElement element) <xs:element name='Table'> <xs:complexType> <xs:attribute name='Select' type='xs:string' use='required' /> + <xs:attribute name='HeaderRowCount' type='xs:int' use='optional' /> </xs:complexType> </xs:element> </xs:schema>", @@ -575,6 +576,8 @@ private class PA public static XName Match = "Match"; public static XName NotMatch = "NotMatch"; public static XName Depth = "Depth"; + + public static XName HeaderRowCount = "HeaderRowCount"; } private class PASchemaSet @@ -600,8 +603,8 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr XElement para = element.Descendants(W.p).FirstOrDefault(); XElement run = element.Descendants(W.r).FirstOrDefault(); - var xPath = (string) element.Attribute(PA.Select); - var optionalString = (string) element.Attribute(PA.Optional); + var xPath = (string)element.Attribute(PA.Select); + var optionalString = (string)element.Attribute(PA.Optional); bool optional = (optionalString != null && optionalString.ToLower() == "true"); string newValue; @@ -618,7 +621,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr { XElement p = new XElement(W.p, para.Elements(W.pPr)); - foreach(string line in newValue.Split('\n')) + foreach (string line in newValue.Split('\n')) { p.Add(new XElement(W.r, para.Elements(W.r).Elements(W.rPr).FirstOrDefault(), @@ -630,7 +633,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr else { List<XElement> list = new List<XElement>(); - foreach(string line in newValue.Split('\n')) + foreach (string line in newValue.Split('\n')) { list.Add(new XElement(W.r, run.Elements().Where(e => e.Name != W.t), @@ -692,11 +695,21 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr } if (tableData.Count() == 0) return CreateContextErrorMessage(element, "Table Select returned no data", templateError); + + + + int? headerRowCountAttr = (int?)element.Attribute(PA.HeaderRowCount) ?? 1; + if (headerRowCountAttr.Value < 1) + { + headerRowCountAttr = 1; + } + var headerRowCount = headerRowCountAttr.Value; + XElement table = element.Element(W.tbl); - XElement protoRow = table.Elements(W.tr).Skip(1).FirstOrDefault(); + XElement protoRow = table.Elements(W.tr).Skip(headerRowCount).FirstOrDefault(); var footerRowsBeforeTransform = table .Elements(W.tr) - .Skip(2) + .Skip(headerRowCount + 1) .ToList(); var footerRows = footerRowsBeforeTransform .Select(x => ContentReplacementTransform(x, data, templateError)) @@ -707,7 +720,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr protoRow.Descendants(W.bookmarkEnd).Remove(); XElement newTable = new XElement(W.tbl, table.Elements().Where(e => e.Name != W.tr), - table.Elements(W.tr).FirstOrDefault(), + table.Elements(W.tr).Take(headerRowCount), tableData.Select(d => new XElement(W.tr, protoRow.Elements().Where(r => r.Name != W.tc), @@ -756,17 +769,17 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr if (match != null && notMatch != null) return CreateContextErrorMessage(element, "Conditional: Cannot specify both Match and NotMatch", templateError); - string testValue = null; - + string testValue = null; + try { testValue = EvaluateXPathToString(data, xPath, false); } - catch (XPathException e) + catch (XPathException e) { return CreateContextErrorMessage(element, e.Message, templateError); } - + if ((match != null && testValue == match) || (notMatch != null && testValue != notMatch)) { var content = element.Elements().Select(e => ContentReplacementTransform(e, data, templateError)); @@ -815,14 +828,14 @@ private static XElement CreateParaErrorMessage(string errorMessage, TemplateErro return errorPara; } - private static string EvaluateXPathToString(XElement element, string xPath, bool optional ) + private static string EvaluateXPathToString(XElement element, string xPath, bool optional) { object xPathSelectResult; try { //support some cells in the table may not have an xpath expression. if (String.IsNullOrWhiteSpace(xPath)) return String.Empty; - + xPathSelectResult = element.XPathEvaluate(xPath); } catch (XPathException e) @@ -832,7 +845,7 @@ private static string EvaluateXPathToString(XElement element, string xPath, bool if ((xPathSelectResult is IEnumerable) && !(xPathSelectResult is string)) { - var selectedData = ((IEnumerable) xPathSelectResult).Cast<XObject>(); + var selectedData = ((IEnumerable)xPathSelectResult).Cast<XObject>(); if (!selectedData.Any()) { if (optional) return string.Empty; @@ -843,11 +856,11 @@ private static string EvaluateXPathToString(XElement element, string xPath, bool throw new XPathException(string.Format("XPath expression ({0}) returned more than one node", xPath)); } - XObject selectedDatum = selectedData.First(); - - if (selectedDatum is XElement) return ((XElement) selectedDatum).Value; + XObject selectedDatum = selectedData.First(); + + if (selectedDatum is XElement) return ((XElement)selectedDatum).Value; - if (selectedDatum is XAttribute) return ((XAttribute) selectedDatum).Value; + if (selectedDatum is XAttribute) return ((XAttribute)selectedDatum).Value; } return xPathSelectResult.ToString(); diff --git a/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml b/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml index 64cc21e5..2ab6983a 100644 --- a/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml +++ b/OpenXmlPowerToolsExamples/DocumentAssembler02/Data.xml @@ -15,4 +15,21 @@ <OrderDate>September 26, 2001</OrderDate> </Order> </Orders> + <Items> + <Item> + <Name>Items1</Name> + <MinCount>1</MinCount> + <MaxCount>10</MaxCount> + </Item> + <Item> + <Name>Items2</Name> + <MinCount>2</MinCount> + <MaxCount>15</MaxCount> + </Item> + <Item> + <Name>Items3</Name> + <MinCount>3</MinCount> + <MaxCount>30</MaxCount> + </Item> + </Items> </Customer> \ No newline at end of file diff --git a/OpenXmlPowerToolsExamples/DocumentAssembler02/TemplateDocument.docx b/OpenXmlPowerToolsExamples/DocumentAssembler02/TemplateDocument.docx index 45e8c9948beddf2ad581c4b1a0db736ad02a8b9d..3b45793a3b46bbeddd53f4d80fa8af7e1411b941 100644 GIT binary patch delta 13479 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 delta 9745 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 F{{XOgH(3Ax From 6ea34d8f64567b9200f5a422e41728d626483306 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Fri, 17 Jul 2020 14:45:14 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E5=8F=91=E5=B8=83=E5=8C=85=E5=88=B0?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0nuget?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/NugetPush.bat | 2 ++ OpenXmlPowerTools/OpenXmlPowerTools.csproj | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 OpenXmlPowerTools/NugetPush.bat diff --git a/OpenXmlPowerTools/NugetPush.bat b/OpenXmlPowerTools/NugetPush.bat new file mode 100644 index 00000000..bb653544 --- /dev/null +++ b/OpenXmlPowerTools/NugetPush.bat @@ -0,0 +1,2 @@ +nuget push bin\Release\*.nupkg -ApiKey 123.123a -Source http://nuget.cefcfco.com +pause diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index c7220506..e3398957 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,6 +1,10 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net45;net46;netstandard2.0</TargetFrameworks> + <Version>4.5.4</Version> + <Authors>yitian.chen</Authors> + <Company>yitian.chen</Company> + <PackageId>OpenXmlPowerTools-HrRd</PackageId> </PropertyGroup> <ItemGroup> From a8b6601f09c59409c5383d8744ef7502b373b652 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Fri, 30 Oct 2020 15:40:59 +0800 Subject: [PATCH 03/20] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BB=84=E5=90=88?= =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E7=9A=84=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChartUpdater01/ChartUpdater01.cs | 59 ++++++++++++++++++ .../ChartUpdater01/ChartUpdater01.csproj | 8 ++- .../ChartUpdater01/TowTypeChart.docx | Bin 0 -> 45664 bytes 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 OpenXmlPowerToolsExamples/ChartUpdater01/TowTypeChart.docx diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs index 5811c0e4..b3e73ee3 100644 --- a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs +++ b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs @@ -14,6 +14,65 @@ namespace OpenXmlPowerTools class Program { static void Main(string[] args) + { + // Example1(); + TowTypeChartExample(); + } + + private static void TowTypeChartExample() + { + var fi = new FileInfo("TowTypeChart.docx"); + + using (var wDoc = WordprocessingDocument.Open(fi.FullName, true)) + { + var chart2Data = new ChartData + { + ChartType = C.lineChart, + SeriesNames = new[] { + "平仓手数", + "平仓盈亏-逐笔对冲", + }, + CategoryDataType = ChartDataType.String, + CategoryNames = new[] { + "1:0天", + "1:1天", + "1:2天", + "1:3天", + }, + Values = new double[][] { + new double[] { + 100, 310, 220, 450, + }, + new double[] { + -11323.65, 3101, -12220, 15421, + }, + }, + }; + ChartUpdater.UpdateChart(wDoc, "towTypeChart", chart2Data); + + var chart1Data = new ChartData + { + SeriesNames = new[] { + "平仓手数", + }, + CategoryDataType = ChartDataType.String, + CategoryNames = new[] { + "1:0天", + "1:1天", + "1:2天", + "1:3天", + }, + Values = new double[][] { + new double[] { + 100, 310, 220, 450, + }, + }, + }; + ChartUpdater.UpdateChart(wDoc, "towTypeChart", chart1Data); + } + } + + private static void Example1() { var n = DateTime.Now; var tempDi = new DirectoryInfo(string.Format("ExampleOutput-{0:00}-{1:00}-{2:00}-{3:00}{4:00}{5:00}", n.Year - 2000, n.Month, n.Day, n.Hour, n.Minute, n.Second)); diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj index e188d465..b36deab2 100644 --- a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj +++ b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFrameworks>net45;net46;netcoreapp2.0</TargetFrameworks> @@ -12,4 +12,10 @@ <ItemGroup> <Reference Include="WindowsBase" /> </ItemGroup> + + <ItemGroup> + <None Update="TowTypeChart.docx"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> </Project> \ No newline at end of file diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/TowTypeChart.docx b/OpenXmlPowerToolsExamples/ChartUpdater01/TowTypeChart.docx new file mode 100644 index 0000000000000000000000000000000000000000..5e4ae53213cc256e856406b8477a38c57d0ec12d GIT binary patch literal 45664 zcmeFYbDJgmvNc+^ZQHhO+qP}Hx@=dMZJS+om#r?_erv6L&b{Z{z3wM?cRq7w<})+@ znZJw}F-F8l1!-Uq6aX*)2mk;8LI6QI*r{7U0Dwkl003kF2q0}?dpj3XI~RQwPX|+H zT{;h28-fB5Ac}kdpzr(tv;AMZ0+Xq-_6q_CVOJ9G;MTPiTgkve6msyOu?mp{j+-7M z^@|_#(?yb>yvE#YWl~mYznjptw{kqU&G~sUhaa{w5AcZ8woLb^a-u<WE?p1VGM?LC zx!x#{NDiBrwgk!G0`|OK9;b|4Ap#)HxhF*=QTQYyJt5T$Pk}jdDSeuvo|)}T6kc-H z0(|)M{Nvl*L1N8RtRoKhm{F{(DP9_mc2h}$1QRxz0-M#zR3J*mQE$4s++PDH&X41r z%#edkQLk~qAw1^|?H#^Y!1Ym7;nt3{CnzbyAf${T1(u4Y-m+1Jv)#Ff{En0(Qo;_@ zL|;p2#K&^tv>wCaCSZV<tq5On5MDeo+VkowoHo^R_C{MJwmuug)Ic8DUIWz8_wNgu z@kA=}`D+@zcU#<G6HfB{nY~T~A&P<lef)yd+*j}-I1Hfz3U3Jp;FkEw3ZJEY5Q?sI zvr8%E3e)gH07}V?j+4O=Zxg}me04v~Ps`kB1&BG8y4!n=H*AkqPT4&R(~e`}3M*!S z)7Tu7Rr?#Lo7otKtGT4$g=~I^tK3}kpZXuM;+=+C@8HL#(TDL)RF+5a&Q-RJ4#^TW z%}huu6W^tiinDz{qDMW$Ph574a(SbPv66KYOY3*>m34~2zJ|2gXk8xKe@FS(7chXr z|AGp<1gzGp?<;cONC5o}75Yx5HqP{Pf9?MR5&swC!vFZ|Rf+vpgA6bNSHT~_bKQz- z{TPLE^v1L67^~nA+LAKJ>nm2vpC3FcD?qv@hT;?R3rVwH&e>wFJIT7&SgES8QQeSB zFM5O8Z(SY$DWP4(j2=r4doWpl9?d?+i6tq=gQGQ3qh_$c5}qT{r}~f&sYD(ROQ9`^ zC}(~flQb6QI;t)|rTa1GXD}`<SxIPngIDm1_JrYfOk?^%neo@BG1JD!4Qw^&4yl|b zwK2t5Q9jUM*)Y(PW+xa`L1A5Y&7FD`_LdGuhSEU(gp8zr^D)yw()v7#`h&^Oc15V! zq`zyAovkZ)_gygmJwHf8F9bnA0RZw40RX-~0PglqCiEuu#;&&C_4Kbox}iR0x6g*q zgMQ2n(ZP-MKu<VL^a%}Q0$nIM14=yCQkO`f(3Im+FF&tr?;F)48^|YSE+N@+w%O<Q z_#21FY4nBT{ZIJ*89cqIp-sAllOC+BlW7)MrBd$UqLanvEep0t$()3iY10lWc4loA zBmc(x^WX#9m`4YlCMj${S*D40sjxGtX^w_kQjLaWRwa`>sQt5$UU65`vr$6n<eF20 zW~{6YYXzvh=0cyRv6iicaf`#rgr!ABzP5sxz>Ji-io|2XAc1-Cvzm?Qh`=<cfP-*2 zj&QrVFesXqE69N^2#6Xk;Y%8!@1aw_sl+s+k_Tp@_YV}^Fc%cLL&t!-Ox3!!oq{5y z5+lnL6(6l-V1SzP$-FzFwAuhma9o(FN_lh*5G`Jz6Ekz-5VbL8wKmQ0f$%?CDw37_ z#}9M&B4@36a>Ch8{?$yD(ZL<<q#A%a*A<$Fu6etM#TIpKrvhyDx<<-qn?1I&ax!W5 zDW#DmPT(F<FSK8#KWY836IRGQKnT5Jlw~-08XJp3C^m3?5Lvws5|N=Lz;|!}K`6QF zcib@)qYaBYVMMdvhkhSBG^rzyZzD>}RT+P=n!)EA9tl3@;7(b$yBB)B^wf1D`{-WH z-ah@@yo#DdTMuNeTf5$tAN%9`i>Jl{wz*s;>CJQ))R(T02*M0_Z%zTP?`ucxy^PSC zu?``feYS_^?i{sOmTY}SXGh>z{w}LtmaQqEgo25d7Lz@ksd8I3I{Ps?(LPVln(f!J zaHUko`y<g>=`zlG+($%+owt$hY;v_n0;4Mgi;nZ`shj*tPz^Naw(YB{0MT}1<e8_N z^)_Hgv%4&YOr;Io{UQ_RpOg@&%2?2vuA-8lEnzxDb{AXvM_JO)BL%ARix9qy5CYkJ z&q+VL%$AF16A`lRGFAlj0giMq$5tlsITnJ)71f$D?If$rAZ^11=3uB_c(+l45zlO= zmWVj#;2g!!V?+I5q;qGPOHiJ=2L%aj@R0WLM$PT$@UrX*I=TlQByBO7ydhCDphwZc z0G9Yb7)u74faKVkTchL#11g1z{9ec65*6h{Y(G^y_JA^;%yuapi0{Ga>S)yA>Vsz^ z%`ZV9tC6pf-2SYHfRjWC0dbsA>nueIZ$B+|8!Q|3D{(G*L%U*lO|S%rg9DAR<nI0= zyx{`<Az)|_O6uSzD!p@cwf*&a6vq#Xu%V;O^ZfI~4`~)USK@)8S>l(LK=&(87ALVk z*Bux$1}u;F0j!uZJ>Db^dnVVe&3Rit`fozPM5q$3n769N-QP-n*TO>laUOFs3-!EE zr3u^)=F>Ji?T$PcqHX|g9G@Ib!7DL#y=D0dZ0`C7fFIjVB`ebYYa5VSwYM&00bD8G zESgqxPx)1$nF^AuuI9q!vFLU4A~79kuSP{z8yry}x<Hosjn_NB-khhprkPVheP0d5 zPP;C~4fUVz@7n-g6a1xtCc{2}Fk1ZWQTy5jex8LHA62T}IJ|w;P+6rKlA~Z!U?1Jw zLr76{<G$&!EQQeE&p{n~K}Oy@{btkb=ZJWHa(YSF<4hEGmb*q2sq<-1d^QlxWTYdd zcb@>&KCiC9n2N6*C67XwM)h?(-*IVAwOUh3x&^`%00%VAEvzIVd(Tmb>j(+=voJzn zJEg#wbj}ExqjS{y#lmS-#*Or2i4END^BWld9Wt36uBlbN!PFcK000L70`PCh{1>nI zpTPOw90TxMhJ4@sfA?0EA}t@nfD-yd_6a`UjUtANkC`6Bm{D!C*D^anJfGTxp5kxM z%*-Q39urM>Mala#u?xbsZa)W>moHmrBDBXq1UM>mBc=xFIgwj?DQOTdIju!XNC=G4 zAWKirMnB8clqR$3LRLpNPf{dyjz`HV3LBK6;7V{IS>9w|A+9?Yi;7<b)Dcy{x+o2w znCk(?or}=D@8-|ua*c1Vnkow@UvUg7!P6Lo#=2kun^6OR+<+fvg`>qTG$X9@7Q(>M z#5Nqc$I!X7{h|Y(C><&tpy)_g<wG>8caU#8Y!)WzBsiqkIg72bw`rF}FyNqO8BCB} ztnpSvnKGbXYnqsy;4uYqp_>l*xG(5J=6II03w^6D(4?wiQjd^hDZ(dNp@unl&%npL z|ARakKTb!1U5_8nzW@^zeIR(dLTXZDi!O>uk{E>dg|~?RJCy!CD%o5A)cJgq+zKcF z0Hp6b{*FpBdwUl<dlysZzbbiC>Sk;K1Iox1`>H#^hP9vwPJtYo^~U6;nfW6iSFsiI zJ+UpS?;Ecug1ZB(QED_$X}11XDKD?fqt8xzYv~#T<sUx|7@s&OB4#o+=dY)AD~1PN z<N8qtI?$XqajW;E;br<pB3)_A(5BxWeF$W<C>d|s)~ZqQgxcfvm`-9%EKauJB2FaB z)?yS?Mbons5W%;SmXc+R3_I>Lk1Nlpu{a%bOfk?7ZheeI+Eui?EI+R8B!1-1Ho;;& z00@Q@*2P3!ipj<+F9OAQ2MVZ0qdXDoLfXy8u~;P~`W2PQW<C-(&quZ*>rheUJJYg` zpy@q;IacwzSpgV?(t4Y7Hi{d7C1C|;JRkpr=$Zz>Gj&Hs8Zs5Tqo|~Gy1Z(Vp#JJ# z-IkP>|6HtooYmdqZ>J$$b)>Sv<eX;-Z;v0a$>6$j*h&M-S;uPVMIFjLdT<Yg;<iik zPbodLq{22pe_4FLdoOxtV}#+ViV)7`?T~o(p45U2r?COMWMxH9!giw}U^Vy+Bm;4w zac%vp$%tV7Tw%lzw^eM4vpQ<O&dg{q*7dwG9XjCW6XBj#IOlD2#P2`#O&>oG<ycuB zF)oTJg+jUEH~K5)znr8qM~1rW>VwvXBwrg4mG+--Pz0I0<Ky(&foeicU0ZJx@OacA z-iL=@hN+djRdy`P2C%fteHq$mutE;Qp>#&d&%6PRdE^GhsDhjm8V9!fxvZ6Rr%~aQ zS8LnxK@<^&3|-i0Pq40>)-PX9WaK4za{Z{mf7ftU3Pxj6+0IrpRHx|21W6cXtfU-1 zJ~)f?rvxN&q?7G0p8A8ksIFA+(CJO?!T)2dmY)H1cz?%g(RZx=Kcv&t&g6fD>blb! z!?$YZUU0uY&K(7ZizSb@%qmIhl$+-ZAcCG9;`%|t(B-TC>laJO562RnQKQ3;``RY0 zvr9knD1(U~hf>puF31G|k`+#L>dyCX%lj0ffvzHdiWCy3=5jS%dY|7<Y9`Ysi=8IH z0^-@IS#t`Tow){A=2?-4wjktU8mvz2%8)c@)3TX#sFL<MehgHU#uQ9yrC(tuXd5ZU z6n6SGZNwvG^E&)E$;23Oqb2UZV(M?@xCq(<B#2;$?I=62`i<hPiaYCp0HNY4kz`oJ z+%FrRut#Uf_9NLv@`OQ&JV%7RKgA3QENvWOZ>Lt%P;hcxEDoS5a=*4~#}0ndVa)&{ z%^nyfa5;e>@!e_w20EpYXbd|lvoIz>^Mar2)%#?%zt@iiuSEVGJPllwJxEerG!~ZH zfHt|wx+acX2d21xrz6mY9<&}+^iHq5Fn8oo|L|nDE}6D2?%nG{)KS4N10$5zZHPD) z&zIz#*St_f0IdZXUMn+cIK~St9t^=9KzZB??L91E2}Wie`INKkXwHHoT=xcNi_YeE zV{A9NGf>?**HF=%;nN-oQTMCH+9!imp*GeR#zi@;P;oDuPJhM1*S*AAT%@NaGHkQt z?71ar3SliMMUV*`0e-L*xDWLDDZXmj1&}_(Y(aMqi0Pk4EF9W}A%s#Gpd|SMMV0Q- ze&_6$dUA%?!2|EiFlH6a-Tj>|SGBJ$YMtWSBTlG65*TttCl=m1(p8ii?%RbdJM$#R z*W%3C=Raj&^p_5%!D{NZwC_4FDv~3IB^Ax|SNo7NA;`n}`y(!BA6E|3P@M=`>#foM zjH+5Jk7$D5O-D^;006ZAMpa`ALnjw!`o9m1e<AC+_LTklC~7bI@mC*GJ1PtRL*yuQ zRs)(~&QL@W%CW6TEXk5E95c?U8XENZPhFdJVRVaNJgEEM(t$v<T1|Z|;h)TB=a>F- z?D)wNlBpLSjal$71T$TpcN|yjSJoW!oAA@hM%hMcBrIncm$AlJ9MKlpCi}TB2RD6I zSz`T)Xv9Ly8_ecy4E!q}yYQD{n-)PB{L_jdun38$n`P#595bCQx+2Kg1xDe2ID+dD zO)2+gO^vzDj$uMdhaPcCEu{%d&;s-X1)>tGvS(_T^J2v$L*7_2OE~tWAO=Ak1@hBL zJQby)H^}bPNJ=D!ECj`U$P3ER)M_9@+F`wG7U=>|h+{Wnkugdm?qx=rKojz9svu^_ z)t&_qF>}lqV}-|=R$`(2v0R@ZMreQ)38y%!v}zf;(e@~f$QL$(4*%pIFc3oKNjA$; za%U?j^m~Nl$s&hE=VG?^0|o7r0C3QD+ImBSY~*WSWA;lCF5iSmJ-)X)K>~}6B8ZX$ zg+bkAyE4*wO&COI-Z~caBg@s<WJ@a~Su}W~yN0vm;xYy+(h0Ce@nDfu?Sz-@h(`o& zwwGK3eIoFQh2%cS$Uv+JDN%6c3#>XXa2QiuWehh`8m+J>paEhc>{p$KWJ4OZcu-J2 z*UyT%IlVXz4fSHg;q_ZZ9ra;x)aCxvQ6=Ip<z)s|N46VDM5gf?X)whi&u5pp8A4GI zY=Bn`lqAwwU<^GEN+iJ}2^o!DVa7o!0XRIWIUroP=ZitDUUk5+G)sJUU{NyZC0R$M ztWft2aLAh6X~c;mfV-c>FU=5bLkgdp2N1I&ph^WR5aO2vB+kO3dH^(l%%l7m7656H zyLU9><z%yuH9=)<C+m5;U8e8({Ofy=hOYm9H}Um(d5Hh{F%|u#>+^Ur!S74AG<aBX z;N*Y?U5KdNW~nMgy5ip1B;3g&4aFupTZM)KRqZGS+GZu(fYnb&>A^C9$WPNokjflt zLuzP!ZeL!nZ=|6rtmI9DWtuOnEQcR0hmSm2zode#Do3$xj8R_2T&Qfwr05=@p&=$? z@q`?sDH55<9%hqFZkif3+7yr;ZOrNswL()AvebZ*PME5eK6J#&WXia-$13^)aQ;lp zgH%0tc>`j6`FTA3iK~80R?dJ&v;tEO22aTClq1|^wGkjrDILIiVb%JvXs_4v+=<{s zWjG$Xtrl7y>vOw-E4{pKB1aKLusmvByD~hr!7>(-w295zXUtHhoO8~?hM1Vu0GHj( zt%uH+sZRV`BQAd3mG1LBjf)MMZkIM{VzcjXs=W(V=QDd^yAO4;JqWc1*1LodNOri_ zCbNc-Siq_`2!&xPL8(|#!no^=FiZ&=ajYd@4}D6_fizkD=kbd=;c<IR<<8wZDW#jL z;UZ=ILjJC^VQPn|3?|5aoY1yCw;_f`jNe@!RJNSO1^#oc>+J2TUg;tGJHvaM683f* z6C9POVI%icqPen<e0XIX&WHI$t9BqN%qwgqE?DfMyRZ4I(^F=!;F<A>kJHqle|aba zJgWEJAR%RuwaoD<A)c_n2c(`<Bf~990;*QTGjQ@!j^b<_qqa2vfDA|o>g%Tq2gx&s zr(TYcdMcaPi+obLyi3fP+ix8gJ)=1rPum&y?8n=HD=tA|i!&9~xIH53Y3_&P>R9`8 zvwm&xRjKQx<cVN+kF%YRMST9ZTmIhWo|l8W+RxXw=w4sPn-l&TT-4KqY!k3#R=v(S zt8_7vag5Yq^;8(DUzNrqNTobEy2NeKgQ-Cc>BYho7cxs6QI7p}un*fpW$>U%yVh_I zsYkE5y$f9|C}{y&)dr=2KN}jKJCQakodeb(x}=rIc%WHu+#|<&nBY+;i%m)919xI% zVJ|!LuvBcyK*w3Rn<OCOVYI5<Ix(wC;!Bq8+%gZ5tyTfEt>nSJyUTKjgz1cEvg1e! zqCGguRhEgH;zwF`p^T}eamAr{iaDlXT%O6{sZS38G}9TiP5@hYKI-s22-9Gc>}b1P z=BE_!7W0(PJBEolJ06$Pl&_qoaY@Gqe9xM^jDrS=x_qO7aB^Ji=5-mcY}8V5a)Z>= zafp53Q!L>rD61M><XGn8KlDtgHy^ZDd$!c{T4Objq|}td_t?jZxwPXtQp5%M0)Fe9 zpLF!P{hBq_(C+qFxM!X$i@lt!ET&>2@ithEB6Djh0^$IrJNr^{61$Rzl!udt<WS?q zpGHPeNMl}{f9?5@Db^1d)3_m&HZmlxuq(r*-Lm^?S*CnmtC3^yiW(-}X3Oc3Oe0gG z()Y5}YClRJiEKT;G_tl`-?KHoN$uagu9q{a9dT$4o$u7ApvBE#N0D-}z`tYu;cCjH zg8LFLmC{(UQI30{FWz2Q*<^d^@9*5}b*4A*L2Y#ZMDxe!j~o%1X4a9Nj?jnhSIhef z*1Ih1r#ChKu}VdKHDAl(h`XLIP4`Q!Dt>tdkez}@RXd`FSD!63{Do*GJCJ=CF`cSg zbLQEbFR0r(0$|LVd*8wEazS$!?$t^6BpcTzS2G=r^ve1|kw-eBt@s+}UeV~2;Iw3Y zX^h<uC)TFR`S!VuE1VF!?c4PjU}}fpmPN;nz(uR4_1OJpt?JowJuc?2U(3_9>o=9` zGn44s%i_Ko6de77I-ewcw$md4p8yxAN|8}kk0s@gr^QVju$R%=`i3V6JZagzUFF@= zPe|eW(mhGfmzzSmBRS2sTO6GOTM_uE@q9J~{T-0`Lzly+*ce2U{A0uPoTqOpIgKkE zFVX3n-{XpZkaCN(7>rCH000A||4urbT|8|}|3x~qZ0)}}@+Wnwe;<%bQxjHFhguTZ zT=g2&MWZCn^`DgtTd|YcZB95s``HrMrju7#{qws`=eVo)0dW1i7w3XW_{KeyO);GS zfw-HE^ykUDCjL^yxhtYS)a9lYTQ5wvCKyb4UV%i?WM*6W%lIDHv>d9!R9Yr7pgz#W zQ4xV9nboc$I8FDl-4P6dh|s?<lK0~9`*@rt?qQj;$!O_%77(~LVjbbVBPmR>)k9cd z%IzzBi&r3s$%=v`M>UNIx_6*HNPT`xRp(@7--x=90+Vy&J$gl^ioDap<UCu@K00aT zH)l|1u;=eSS%=<lVmw^{+-Fe%_JW`6MCI`@x{xiN;uPt+>5ME>VN%UH{g4k2CKTg~ z9N{<^>YJem)39b7jJU=m*vtCOFs6BpiQ|)>^5I1-u3beVn|~k#QiF~@4QcMd=u-NS zP&q`U34IiWgfa$zhP<mo*DJ-n-rB1|iKdV|P9`(kJbCkB5GYq&8@)t#U&_qh^!rQ| z#AAJJ66h2RL72=$>gA4ZGRaE>EQWa=O$&W<QVTt`9om^=J9zs|N~)7%bP6qVo4sy& zgN97hxe?-$$o?)H1h<4qLlB%aMil#G<!dsT4Y^>7RZ$`14MT8=k?kQQKEgoP3C)-# z?X-rb@gqNZ5dBB$IGyc>xgg4K&reYSH*PMxTpVMQL@|FBj2H%`7y5;FbRr*x!&`y1 zHimJmWCP4RdKeO^B&XRI#XaNPKs68A3=a(a1=`S-^<)|Y5VOg|pJ&~9Af0YT#`a5G z9p{-J<-?lmXblzcPw83r)y|E@$(oM@t&h6hSU<wZ&w`3Y9PCY_j;<T&=xt~jKxdia znZ{5R>pa$hFF9Wn1=&|&d64Ee1^yUNkCB;xwgaB1vZUm1nvb`NBTZc%W56rpH!|{P z6#OJo1TW88x55o*7tODF4wLEhCDR_HOpIw?xQ&vh98L#yqU1}+9BQn6UbUTrlVjgh zWQFlHMSt44{|$777r*Q@2a){aEc%2mO)be~;kIDZfVv<f@O@M?VJCA032s#hH~DS` z=6qpkRL%feW57_b2S)|^q>G^J!NmAorak~zvu3mw{XkA!I`KmllqE@n;S)RJ43W<k zc^77eGmFGM>I=3F*1kV8UwbGq5kL;zKD0e$Ku0WTx(osi+Gcfq3D2YDyw{oUmyX+& zXCK>A7<v~+$9Wb032ACcl;Y+?Y0Dd>#_a;@wvrY%Wpzl2r>y+a6>VP0QVCDxd7}_f z7Lx1*8wu;0)moc9N)hi{GgKI~?*etp;7y(X8usH_n{jjsTbjs>E_?TU+I-PRg$NZ; zYO`Kn^nTBsa!hS>8+EISHa<+A%i?|Vz9wxaTR>0&sPBhp?eU*P4HLMND>yFJt_p{i zb^R=UZQpnBe?l1?l+v>MZ%JeKjX~)DUuk1+WAEhrH_Q|z$=VGPAc)l(IR+STM`~+2 zvT3U8-h&h}4oUQh2;4cp1uZl=trIL7vftfo0U%-D(<YKVq0wofm>1gGJjcQk;%H6t z!VLuIV}!=?jMWJ+Wf!SXcwFrio#!r_sygHJh0YD|v0hIIfg2i=jbTF6yS!x$9$Qdi z+X-l@VIYRZ?t&)CJm6MJwQLG-dkx8T?m=`I2T<6QVf1D#X4qtmsb$#YjAbSdlk)~C zBcQC}n*u#_dj9;BVl~x?++EP+{PXhb$Avm&?ZqqNB7b@<vHVD_S=kbEdTH+nJ-*@; z=dH_ocUIBuo44)%)PUcuiN7~OfPh%koSpAWe|_oxd!bBijZ95UEbYvl>18dAo$Q_M z&0O?FJ&a9l^wsU1teq`PO~1!yHqIXZdmP;`Qa#oA-3`|KekA{KuKd>$|L5>eD^Qg( zC3nVv5c(w1C44|@rK6Eg{X2OWR1G3N0G#2mss3~&)jZ(w;%W%COsLq>zH#g;`)bmJ zCs&6aTir)M2-}BrdZM19@64boPkry<(C%IwMPeNLFeqHA3Sju*{@&!aAu0e=+`CFd z7NxdGL|3@54hE5@HzV{n#ojtgn&L@lW^flq9DOldZr?(L7A#}VMxRVKH<ex5yT`@B zl$YYWuK#iY)lVZAHEN^6+rcdSc*XRoDlp`G@4<P}Um)WKumUmE#tkwuGXg`AKjXDC zAaU@(E*hvfnXm`f#CZ09`x7?V`^{8Ddmn5kR0Zxyl6on?9?_-A`GqxkKpQGvqH#8{ zw2PP)R(;)e2j}sNWyl`^V_V)$4Dj*=WRZ9tURLYpZ**a=&6T*tQSSW$&xjl89A)Aa zC`tjw=|FF=z;9QBoMgU9%!IcyQ0^QFmppB3Cg_abKih(QaA5T&Nq%9$NHSMJ+lb5Y z|KvLd>uhgRn{o6mLD!LZ#)ruPUKd*f-Q)a77CK-G0||G(S>CWM6i)~xNC>?e>$DB> zMfSw!^jd97>c?i#USYETvEcvx9RIyD->k|&{1?#5{KtawPjUXA-v9ur5@qGTEhvAv z)WS!f7B}M&grwaCB{~UJ`~oC5;G1I#Nw7D2$#D==u!4cb{k#3%$JaM`Vopa1ANN?Q zqLEOziCf&O!_r<IUBRiyoKnRct9FMF-4-7fA2Y<IJSp6|<ESdz%6>|ZZ4-+v+=$d8 z%+RT0K_VC9grV_f1Zw?~)!Z_At^r&WQog7Tt7~P?KTVp+@?TCZIf3Pm;FLL^&p;h@ zHZotW@fo!te0af9Rkq-?tTW1W;v(|YH?irv6UpjD{_vrd%N|uCVnKRlnh_r%&42LM zYGS#W$nhLvha9XNy&emS#xL9YM;}V;aqH^mcY>gN7skJa1|Bx_-xDlrBYS)6zdEc{ zs_S-p3<$pZmS2Ro-kBUB2nAtKKo$v)L0-Os6*5K<qDbbp%ExLSPq^eDQYXT#n-J$K z$oP2~oOpTqHg}UA`9e&3ArN`1qxqtf$Z9mgF3!Acz9tf)Q6VN>`Gj6YNV@kuew^D5 z^_k8+OaS@ugi<L~z!Qm%QqDv(9+J>?G;O1iK|eLL8c>o+n2J>nGY(f;%nw6Q%fujt zycwR2`i-~_Zn#QAD+EENB7k0*Op9%1Z=ZP`I1wvdEr0RQ0~$>;mEch;m>f7VXrk%F zdxF{7JFc%lJ$qh{u(8NBBB#r>jBC=g9YDK+&8o@14*A<?W8jAxcw+@W5w@r1!^<2w z%t(3Qn;c%$cL8Ix@W+G+YNe<FL2QA~t$EwQo#xPMh}m18U=`8$C+e6}35$spVUfzr zk%-`8+`{t81gIP7!Y$DNS1wp_@-=vQbIOCl5IlXzC@La|66;aKuf@Kao2nX$Q-UL6 zr`<ngLPD8?lYm?bNbdzq9wwLl)`+GNQDo>$*x7}VQw=m1rc#eeYeb(XF6H_Hze&(| zvkUBHEq(oHz7miHiRmkm!no$c^b04@PXLGDBw<_48HF4|X}yfr0D1nj+-Z92*>|6u zV~CPj#uhX4=Xso*>$_U#h<dF-<_%^ZfHsm_qS`c777ib^?KONAY>5F~@6RL!$C7`% zWOV(iu(X+3Gt_Oh!`vJd-g=l_*{Ubn%|ggn0W8If3(p$&7(q%2a_DG*&in1WO`%=V zhtcZG3;DV<DdaL_p}~wbXngu7BH<xONtG~AYY|(t_>@|gl`+|9Q(X`Y72FG+QPLr0 z$P9B+ZG4LEBnYbP5G7yk4_tJP)s1$vQR1+&;c?B{oO4H8aql0@ZX<t+Q3J#RJ~%&4 zRN%g6I@M;(vb4armF73x&a=$NvPCxC-m~<cb*ITuT&_Yla~2%fHLkB$Fvw4F+-f+* zSsmF-AE}TIG!ni3P%uPH1jwLjU@#xSD_HAF&BeEGfAhcBlYZ%`D2VSQQu!wCSl|AG z?^OAh``~{j%zxYm|D&!{CCOWdFdz(Hh5CgvJYj8q{!EVXri6y(ZC-~*aA7GROU$rc zw%;~5si<3t9(fAudg<@7aX)H7)ITnFQWHcPCYUv&tF<ZLxohk71{18Zt-&@|6pRDu zyni%%i;ekn9U-%r0703Gg7N24RB9ZiC6j3RCv4Kdi<)zMPjb$*m2Sbt&`r|)0*r)t z#$G)2b@)5pQ2o`wpRYz;MHS4Rj`QCIht$+0;B+v7YiXlUU@z8WiU6RVIfjj7z`2;+ zi&NUBXNab!iP;sR4JNV;_D9xC5j;k^G>L;Ih<_YqF__kjKl}Mu62$T|x?LK>RSnzh zg>LAFe+qt8r#1G*e}1pUzsC{4TJgZjH{_apLoUYu3%P$w7iapv4}UAbY}IZ1ECvL> zyr!@ITW^3nVoe2!#gdApaLL7vi%mu{4bbydxp|wluPtVh_<24PQOK2}{kNXG&E4Te zXWgH;%VMKsgG0~^d$39E7HpWGFZ*`4pv1<ONefbJJcHnN*NeAzrNers<jPKVhy*NT zgT>8M559v^ddmBf!`K>>MK$H2<y+5UmU4HG#T~bU1nIA=sIZp^O1_X`G*JD|)h6qi z>@C1^T?J_OSxOYnLY1qe4y=pv+N_2RY5?_UDRtp!D218DPg!DC9W?}(=19t6xvcL( z&*J2nOP^uoXfo2o&}V=R+m?RVpBs5^$qy3t`@IlhLp^`Ecab;*Lh+MC67i^U`U>EK zWW5<$b-6a9cn1B0_gMqU9a|0Ba+W@K4~fv@4bf5OyGE~BCDoPB>CtUJ-jRIlr+<yk zKM>b)G~#eTh}G~cEAerTcr$<oSZINVOJtyO_w1>r?1D3eB7JQpwlOL^^Nzec54kU= z-Uo|u(jT`pY#)A7qi4+nIi80?4xL7kPQkZsFqA17JPqi*(l)!a&pO2s?B@TbI9&@b zvP;_Xc5FA8egN|U92X$yG_AXK&yT@fRy(p*?EM2QEe{IWoqUSr<4tv&c}ivj8n4Nd zIJ-(t7&$PSMRpY(fI*K2*wY>1KtgmX@`J=>X^iGEQ8Rfm{LGi}#y<jZTW^x$HmeO4 z8SZWCkM&~4SjLAcU%njO7S#2{YIx4YIMK<<*l5q`IZ5OoVQ?)-TSIT%V@-c6Is@*Z zkr#|V&evQnhzU*pS#1rX3gl7L_Y9*vKE}2CH0mXPr*M5V#U?g9=?q_#{T+J|dk#b8 zrogreQ>??fr!TlZWxRPE#?6MdI_1GqZD4NjXABVhX+`{eE}8g-xLqq0Wks7GihqDl zY{GA#wN_qjrmCWrOekod^0)Ytw`>l@_7ZOnT5#+2Q$K$`I{kml23h_9nvictR{+*u z%KUEv;$mTHYfAt3{$Cwe%^CZ3Hk2Otl`n$hORW~tRk%}>78`Qwq!x<}INo_S+xnj( z!bM3~qJg^Zm<;*YZkToJaDxFr>y~LB?6fVHaVx~6+9opW9|=I4vltL0r`~b++upCw z!prtNa%Ik8%yJrQj@HXO%l#)IvXWd^ZBOEZQWLIi0w*Ynse7@V0~_7-UoYm%bGZ?Y zLAZ7DFL<YI^$5}3Rw?rNm^aoofyy3i#+pGO8)kQ>EW$@S>^~PfjzSkf5`McXB?qi? zH)3WOn3L#syjdRsL$#LgG#CmsBA;Mkqd{@=R!f5D-$a;AV;10|zh*StA^OqigcH&2 z2#!4b&ePuP)f4p&MMUMcVeS0+N_`F$d}68lkTErqCFje3J$U)67f7K#2Ac(Zmtf;r z8Gt3DPr{k5V<vz3@*x<gGVoS9`pU0yyA0D~%HKHJnLVB#xK^Ou-yfPEM+`yq`<#=n zZm38z&gbvbjRE#<yKQ?c56~z|N%_`UJp{Ib2MhLi%))Rr5AN&mDX-lw5kXd)3TZb+ z<MI_%Ye=u520{Rmcp^b1@hUWrFfxT<!~&CS#G{BwV~Q?NDa>%Q+Dq7Ou=g~6eckei zeBK`{)??7=*VSZWBfCjIXhcT3A@y`&Zyio>7!Z>r=PI3yG;j)BYP7pvU)KG<$@a@z zYn~qO8{O4CQSRAuTCd;7Z5+S;5#BE?u-)OO8U4@C_hI<$_lF7Q=qJ0dUtB&SNRv71 z&l~L{NEn%+{CMW}=8RE@j5G=`J+w982pqT`-l1i%%Y$YR_$K-EY&-q83H=Ww)2Trk zUOlMfVAtu4YsML@0IeqaS|Q>SE_PQu+NW*a5IL)_u?kis9(6habx2tg6u-cxI#G&& zrW~U}iSz1}f6x|sOGF?p8#9ezm^1J4kjTL!T1$wT*q|s`x=0|6PK=8oDA^AEc@A7K z{>^sE$H$y-twmr($UpEKVjoZoDtSdGRzc_?0G|+XT_U%tAu<-*0Wc%ics#ow#o4a0 zJ*nTLxo8{6w!ZWuy#@(61JcRr&NBpKA;H%TYnVb)gENU`sb2qDnL_bk!*l?Q-|P=I z(G?*)#b(AOI0*Jhj}F9TaMfw@I8cIoY6fW<czVXwe$+IA8WnJbeT1jbymZP(PzgA` z*22Z952%%$`#T@k)>OoUEmv3mR;R<4;M8TIsTca7bpx-tZ{oRp;>G6`srPcH&x4Sz z74xWDJD+;xgUOMRuNVa{B6U<;n^vuJdP0e?g$g!gbJm8<78;`tnl>;n`%HX;BNJH< z2@zl991z+AYx6_)-M~XOH}o&V>e|djG7SCeYB!jPgLK(DUaM-dr^0p*2a<6&`jw`^ zPoab3I?c;Yw#!91x0=ThYoPf@TM3Jt3=%9fq$yWolU-Mm-=j4lqU!?%q?@(M&C`2i zC<3-gs2WV1b+e~!fq7RShS;GLx#K*CBLHXT;|DsHCGMa}r>FpD;jW;`8Ftb&+~MTn zX=!WNCTj#gQ?ew5s0T4*9Tjt44aZdfbm*4+&L<bH_rsRLnpz4UZAM9eUK3E(rL;KB zcHgK&?DJd!q2;=Sd3<%qpviY@(>W#L3I}eC9KA*V)J--`aGVq8nFg*AAy*F$fym}e zCc#yQ^H+vtQN=1~TRbIzz^83z8yz1JgG;m{!<;emAi8g|re&Icp{4MtL0u{xf8Xq% zPoyQ>B)_@ez+5nOgBOehoyvsSNp|44EkB&gM&cOUfY8+RM<**0a(fUKQ5E*&E{MiJ zWsaiz!>JQ_92VQLJ|xgd{R;+g6K>aoj(p`Q*Ofl6!t{V;j^;>4SoNUF5`6)leayOQ zT=KU;igfE5+qKf!nss%sQ1diW+GK}41EIz5@o5;V#G4iv=_xubSu6E6f>|QO%ZPQe z*gCO2U30&>PK{=#AdOmT)!oWC+}9@vHb0QPx$vZIQdFH{q#iaC2sGc9RYyAP>nI+y zVJyU&Y*R6=OJw@vS4G|kDm`ipmG`hKRV~3*#S<{WLN*91y<T;HDCFpfB&~RV3(NsT z6kXIjZI!nr@-!3QaW~t6L@MPxm5Qjg*8`=>tIvZy1cV%NL*Es<CU3*y&0{!fzux7F zrouY)lW@gG{&R7`N?xB+E_0}JckBdwIIWaAG*MLkdy)^e&iVVZhnns47BIgj%laRI z2}iezLqG$S9v5H#C<Ov6)B9$=DO~$^;e!2F(fWHp__yD)NOj8Y`_;D|;v2Zi?#@q1 zoWxN#(M+uh6_O&f$g^L1<dv85O`VW%5!mRtA;?cr(DK3K#thcnF@;1?YtmiZ%x_cd zy^?a){d1{SgUK?E9!Lfvraz^~(kT7hbG(gz{2*;0(UHvD!)1MD@qQs<bQ?KYj8cjQ z5XwZUt<shE-A19Nir`eVrV>=9q>Tuz)O$6nrlgGVCTYV5?H@%Ck=!7X5xwCj2s+N1 zTBA<ZK%PMR!Q5$G$AC0^Z$z0w1`Vfj<{$y35>AZ!Q|l^+WggrQgu02TqJcc%tg^xg z)K|iNPu@ofCm!I%Qo`^Yd`|Ja*^g*`cG+b@=fxpaMM^6esyTse7!kphGJQ+pLGX_p zDC%WZ!;p`N_JAOg5x+FlaEch36nKU;Ng~9W)`stw*VBG!V?~64&$1LTxkc1w1|(Ry zyU_NW#Td?pO!gnfNkL&#(Wbx_t5w*rxEIR}%<B=3E6{DI29S;+C0gg%f=i!nZQ*1j ztd3&n3i0Z+%<}<?OWtejaLopVju61L(oNGgR8z>(l+Zd>?V63{3f6bJ<mOouO(muV zl|+ZMhL7k=fL)a2J8E{5t4iYY4k0IECqw#il)<(RldCuc33r>DwdldC!seBkFi}_6 zAMg>pYvM&$o5agNl%KBNZ*S}97PD|bv}`}L$-aaz7$#ohgZfnaIw0*6ov%Qd6z8LC z+PZtxOP(G4gr!>$8IW@pwOdqM0wr#CeNL!QW3%D4)}?`MVf35kXomBq&1=c-?s#s0 z_1m1og0no5-Pl|X4>qp)<jMz8aJ+4-GtaCrO=(RcrEiz-)<wIZ+lYUj5=c8<&ClC= zp;$b%e>?cDx!{25@j-sF<0RCx<G~uy#|>KWVNFl(^IST{<+a5C@x!cl{}~-oo&Y(N zxwLMsRnUhL4Laiwx_(NzhX3MR#s5dTHuRwa1^X?6f&c0m{a56F+wx3JlwF+un#%mu zG%8Z8mjV_<xB&e!%-~z?q@XgiR|Wy$hW-dRv`f-%%i?uE8gfx9(4Z(wsg5C_&=U10 zPutON!&)d)rP;>b%JQ@qxhkVs`RTT$Awys%-p5kH#>^pO;BVjA3_6)KAcKnL3PgPI zlU!Xr<Y_1f%@>GMaq)1Yw4E-+eqG8q9j1yJ74$f4LtU<N@<>Zr^I8tY_F4%OBy|mo zGEmllH8WW230(uqzKCG;hd!CT`a<K~$yCw~3Fz0sQDYl6tNT;$>NC9CC37clPM2QO zRvf)K{PNU(8>i=IqPi!9IN7GFjX{E2g90c6mMS6RTF>xRSil!YexpWn)8JY!?oyiD z&Ti!GKUxe7HcS6-elOkJx6R<cw4aHSq5I$Stp7Usm-bVUwp(XF*hD|Zg}5~Ru=p^b zjNqpNLa{`<0ECEY0FfvVWNHZ}AU~<-%q?hzoHb4^DqE54wrETUWA?HSyEAKQ<9fth zQKr*kJDAP$M3@b%tH5pHe1B|qL4pVw5)S2No5kT%0IZFQ!$%v5G6%2!BY+4)q&$Md zrgX`)j9T=Q7mc~4FgR-I$CE|{@pcF52)O8`yWNgw0<~NAo)k;+_ya~@DtvEn^~ePP zv~mVd9qL8LSs=@gxSGsHzb1&YsF#67_Sq6ZihXHabi?yPjP9YPi4ab1l-=W{KL-nr zDB^*lW$}U-r^<X|a-JW^FO@?SGCs+AayZXv%x`>9O3|JvUQ%s`9?MNd2W_SKBO#4A zYhbW%^5*^A>%>l-z5DsqP7wqcC{*Dy+x{P)H^?DS;mlsid7({cZAZ3n_!CST)9j>9 zQl^}v+C=8<g5}C!h7FK=PN*SsNn&q`V#ymyvTL%eW9Q=jkejU)3jJ1`#8vK^x~(B{ z!G*tmiPs>mCBL+3dQNyGg~(}u6$cNnxTZ#;mvaTZP(2o~$kgQJYt!f`f84XRVvq~y zuSz+-l~7`plpZ)W#<Hpdhcc@Ya{N)SoeuV+ikAc(Jtj$7R*)s2j`>{5w5GXPng7xw zo;RRVjg~Z{S=YXeMa9aX>F2k-FPq6sc*})z(y^A~CT_G?%LxcD_bPanJ=7+gwzC28 zv<$PHd-<(p*rDcl1|}QTwQ3){;9vOvWB6`bR(art1OO=fw$c7qw*G^OR@;967pfoq z>{mX5AGO5|*=bM;aE2DRV0Y&)uSU>UHX?DPGs19goYw}y03H^>H9i)B&ST*~zK3Fg zKr~t{f(zj<nJ&ps(HR{H=_V5GN32NqLvYP(Z1d@C=N|iM9A1wv7Qz_g$=mc2-@&bx zA7FCASi>hp_CEJEGv^pF*@Y}ZAti10*}EGa{zoJHUI>o^lt%9i!i08x1eROSZ@-f7 zs+Mj3?4poUY?oll{j`(O4C3HvkYqMG1_6_oSg5Dzr37cZ2RH@;CZUj<_&n$OIPt&< z_mCJQ>Zeq1G)O0aLmDl0Oie2cZJEiICMI(nwU8U};VzO?hE=130&CQsvQp(HD1vab zai^_y{2{Sj_oIY@gd(RbC{3B!qY4U>b{;|;(3H|<MCOg;9QNBv8~PI{(<!|<Ro#g; zk~{(zH3M>C${?XIedt|=ZhgfQz!+Q^>ehm1m_90fx63}H#hnnyUKdc~!mRY<*f(@| zO^^P_9HbI-HI-Oxy=sfPv@RS1^XIk1s9A~Q;(dXhOBJ;6eWDdf&viO7O>cITJX-id z4tN=R!Q3jKHN*HY8OtrrMzrSilj1Zy0&sUDtRd(-q|XmX-V^L}gxOGxCc)%j6bf%k z7CDUZSFz6m0T^u9<S+#or2Q%%2o9cgqnI*rCqIf*I(#O@L|ld&`hopYhOBo|mIs>j z8Hs7C)I8B`iT>XqtM$(iGIYh^w^?%>K%@b51{_Y14KEOf=|cl7v@7zzCnzHeyVDU~ z2+k3}Lnu$~l(kz3MQ<a-DkkkU8L~6&6L>J=RO_|T*bPUWP*&R3phH%RVEs~e8J`1t zZjwk?A=L*BRVw==R6{(gi6)Dcl7kXz=L!;UjR<HAnSF&<rGXJwxNd$Z-xUfY{OU-| zPRZ2a-uC=BQ{VnPOWXE)U42pidVlTh_5KL=_ka3+p<UnS^Hp9y%G8;YniDr$OvrKw zttK;N)_KM0ndSkZ$DuqG#U(1gk+U@Z47F6{Ja;W##l}b#pb$|rXv7%j_9Hu5Jz#7! z*T|+=58D*I=Mj(U4QV)2m85w@C_zd*97--PGMtbs-Pm>s%aTdxCBU#q;phjNkm<k{ zM7=<M>nGoj=3od)MFSQ<mT`cRl(4X(QNRF)BC0q<ZfJ_1&J>_l5&c{PdN?`LC#<H3 zOM_>Ul-K}Ik0^1XaW~VuD8_cZt<9aL(4nct3it%qJO!e^fCa>B7)7Rt_F+9zoV*RM zJjAmuYW?nB7q^EAM&{X=3|oOz$NPT=`#77%7N1n#=1{-@dK8=Y9)K(}FL0nn-0nUz z<_0|RERB|#A``V!Mu#x3IC*IY(|%b&Hls<8UTPlse@=ASgxI9ufU-c8ukw0}QkPmC zR#_aXRd1kHcU7dgmoG-~E)W3;k&<PjjRCO&NnT7#Kw+tN6pdO45O>`Hf>ne@pp+Gr zH8j=OPZX^_)}S0VfEA<Qx@$%&1;uV^Eft~U?JtP|uIkcg@Fu_3goeq3dO_Uuw~F-# zc>3V9*^NK}&Dg+xgqN7R0y{tbJWGdPpPoHw*-XU-$(wZ8Z_cP^7l!)KOZY_(_5RaM z9UmAn!M}w2yh+BsmX!s(XFscR>(Zh2qIK<}<}K0$(rJ3WY(f=6SFwkD4L?DrVU&`0 zbp+X=jDMIlJv8$OVw#89hbO!N;AVs(gI!F~FJg7z7I-p5xQ%7nju8vd2ctI|7s^aS z);6diZx}JJA~$wZ^;eXfwC1yI>3&=4V!3)-%VBd@Y=JeyK@~bWN}bcm-Ig})_KMfE zHdjX-`+k?}n9~vN#+s-9-N?5Ue8zt2itpn#tM|KKVXyx^^p3;!a!O<i805}T>ojE% z>R;8w(jALSiBlhm#hObgWd<Fh=1k|Xq12t6Nkm-qB7^KEvPOqxtI-Sio<;SnErJ7~ z1arGRlo)r$c3#lC4wJfN+S+%5)--tExTAuss2c}t-r|f!(@{);+Ne{^Hk@k}Ryq>M zQ_%7zkP+}}Sk!I%St#@v#vanG{Ddw7V6bTA#@+6OA?#VW>Fn81RtV;F0Vu>8RX$c4 z9TNuOB?FS6j0QY3agdp!j$9BwRw2HT8I;K7`?G_PgQtKyidBxO7M|+<ZPhiRWsiL9 zI#kTX#`Ou@za;H)>_2)7BfCdHC;**p{NUgnNQfN??FRV>YA|>7xQ7tXvb2JnRKP5q zpyqS|veGPP7J*0+qK8?7IGwZQB)!8Bj)#$uNbHxnbpc8cVhUu)g}~Y(F)*ixTXC&H zuj{0X(?pSG@|B(UmjL{I`KthJShm(y5rI4W?T1f(Fq^YEjBa={GI~Nup0OC~THgYW zN&+HgfZ16*qD5=R83rN*)lnPFR@nk{w!%qa(6z@`dVt|nA6ULBsDgu7C9$flpFLi= z3xLdP6ubrw<gtpl6mFiXc=Vg?Ho?IJbXQ{~@{e5MzB4*Hc{T^AdI{I8rpMyQp2u|f ztmzHsjpfehn3kz+z^xb5O<!VrN*u>LON7oW=~h_94u14Wc2cQkifR(Y=*YyXwc&RV zW7$}-Q$hR!>eR-7%jb)XV4jfn?dN`-#wOUuUS&vR=at%m%VwN#t*y}M#<E+wiY`(? zjLAh`^dp;N%E^&e_IqIxNZK)!wfN0YlPB*&{CJt4v2E6&v25qY)hw;DJIbPaR)(2c z2mZ0XBvd@L-a6qPG;N4w-8(Hq!uojnJ%}F2f*b4DdpZzRzuMIpxDgRL_YqcX;VBSK zGA00%I1!n!W&A4jXS)iYn6e0NtAD1bWRl)rcxLlUMoxFl{lXviY=MSs6n_x_PbNea zBRnpUK1%If_r+KdUbtu?z#n_$GFxtVnshUVpk$Ei+=Q!I^&$CFlauh<PV3S}3CUTs zhYxE&gpm75lFT2;;LU*US{a}$_;$o1enNC|#aCIK{u~MnqB3hjJ;)h{1PxZSCUKNK z{Oq^Zd#B7)mz>_7MFR=>%|&Nuhn!OPbc$-^tabJUGg|38g0qBq-l)SD3h}7+X7D@2 z<bkMI7#Ri~9JyoW1onn)f)<J2Lj5KiR{TBvS9BiwDAb}ZPdk{7VwB=<VOF%Rs!<g= zg^R;IsG?Wfsp+qO9HswdAI|<S`|$rJTmRcUyvOlv9!~HV0KT`Nw4!p=u69A{u6|VO zm?3lQ>x|85oKku{vp?@bND4`#ogKJf=YecF%D7?P&)5jF!jP-~?SBSJyd^!r0ihC5 zqE#xqt-hN~qM=K|k}MRdp&vqYBZ{*S|C})7JWlRcyKwO`p{c+JTQfzZG+-F1F$!Ys zN_bF|PHe~^eKao5a5!417+|2};tst&NU!2sn2E@3^iCbQ8=3~-8gDPkXj(-^;wU4e z>#u%Y%<xl3LIVW8I`be<@`~IHaGu`GmdB*=KvE>*ykh%g1-1HF8pnKZLg-xGtiAKW zaNn^db<<d6uXbi$xfbv=)3Xa-#OWDU3Y&KFtR|Om$%N=&53h;ebXfJ3hBkR43;eib z`;3@=$TGkvjP+ecsjhhs`M{73P(&z4TZ9427i_}LGS{xr6O8r`ps^}?ywNXWV{it# znaKoOoO30{P1(jntCj}yT|K08Qlg;25KQE|-Vnv333(#Y7>F`!Q{r(+!io0}3%uMn z-9=ewYtEf2oY<QpYh5=`AvZWMJMOGv!N$QKta!VOfZHHn9_(Trc5W|Q(?5RiEhQA1 zae6W2axaW5@V?gDvu*vF%CK{EmX@$yDYxt_mfhG<)N&y8;1IWVmjf!riM9Z|5reYb zD=MA8W=@fctDB$E5Hh(Wf=`#gK8*~F2=Ks^O<+g8byYRn3RZxVk7rK{>s;(*rh&X& z$-`N>xUKN_4dt-~-xRcG5Xi0K!&J{Rz#CA(obz7Y5gg=bte3hn$BIxoI!HcAV00=3 z$J%Yo_u=-RRE9E5%=sQlYScpvc+wf>yiHLKQT1n1TwS)}=<?aQ=JL&c-r=TUr3<Jn z_e-tqwrpt1@12hU*FD++rZ31!cm;pDCL~DUnU3vb4(7=9+hz{vTZ8Rlbc2+KTtG@o zfIfk5fc3$jZnL`BcC<#)YZFw@<pP_4wxCjodjQUjDMy>o5TwAD!(b|;6x5Oke7uh< zd>-LbNzynv1=VPe702zg(<y-U+I#q{xi<tsw#iNgR>|J__q3ucn<b>*$+rc1z`2&P zS<caKaXiKYwCJm`%`M<r0iG>zPFSN_izpRM_20)I#<G@h-v6YKrm%C;LDN|x9r0-6 zyH=|YiEfP-fAHMrzJfT9C9SlzCi-QFOS20^7&}UWt>AjRk$tH&o32E|&L7wT6HN06 z>Hj5gnr$J$B&P)4l$<_(=2%I7<pGy<#=>q-Bg+Mm<{@_?@m^an602ILD=|HsxDzqD z9mpy01~F*^D$7L3!<7UkFU^@k>nf8mOTLW9;G=A_p;dvQ!<Va)RahaeH>4z@R3O*A z*wU`pTwu=jF8hDjd&}rJl4V<1vc=5IlEuu-lEuu-%*@Qp%*@P;7TZFLEM}H0viP-U z<{r=S%)8(E{=Z(Us=FYfGNZGqB6seHG=Iu(LS???Xs&vrkN#3`{Xq$9v7}nh*sv;W zEbBU_i$h=Xwi(2NP4-@Sm-_KFv=+|QmeX7A+g;^`lA&b&{r9j1<|h+=n)$+Mchu!G zHqAqvK8YW^{3G_Z8~jZ{qhQ*mN99W88rUJm;#aB?(zXvZ`By!iASk@f>G9X_9yJ+` zhdRD#kq0rw5mpx=L@D^1YcKy-n(_+(;Q2{YM*S1$`Jb-i-$}{>HUsnsBDF{lK=w!k z)kFg&ClR1z7}8b-V|N6r#de-qa%Mt=Nc~(-C%q58By=;XVj15^ahk>8L|1=oT7C_w zt7N}lf_l%(0)^|IKq&GjNqJ{ebD4&&p=)y~0GcQGMQ;;7*k#}oVnUYxrlP|t^x&b` zm;`{OoPvS4lCg!@tQT%!kz#7q98@7o%-bY+muCqUHV~3^6{^8dFeTdb5Y~b*GcFTJ zwHEl3r<`etuH>68Yw;O&oI2<8;9EvWnC6$K;km-E3OVxj-gEM@QN5ygF}boBy=j~7 zof|%PP{-kSi=%^gu^CRg8yC%-|N8XjU}%nC1=wjCaFqB@d;R2v{57ioCsE|r*!~|h zk*fHqp9zrsE&_W136NZ72meffbh5(ZXG#^WPJ}I~x!9WPN={u|H(~QAkjtBYc5az7 zPlgr~PTkZ29K5R-#;oSX!&{5bU(XI@BN2r5d9?0C#dQ@uD{Gz*&(K7fVhBw%{@D!X z3DI<f)3|8mNHINoz6pku>+KwjIkTjlZIA7J2dLs%U~mIGw%mwgP3D_PX-_O(Zo*qy z{O%_x<Or^X3Ch`I;NgI;saU!JDyqixt=21VO=BMt^f>awlDC5wl)q^0Rr^HV5Syd< z9`^jJZQz7&Ho5>d`S8m&|3SU}O5pJ)2=)i|^@nYOVyB=0Ei33E-~!>!X4V5CzN9;B zx^f;|ZT1YlMSN7W-qtn`9khS0j_Z_-OXN0#?5e1*uo254-Jifxi)%$^u)6&;hJd}m z+TJ0BnR-Yrc~#oJ7}Ah)TmOa{X}BSTP}El;Vv3)s!70beffL;%${eQqyV?0t;)?0A zK(H)WlCG3|E0*BeK0(HC>F%4=qH|$>BU5a;)iYxLq#q$EK}b#k7{wxNZNkJ2by<U) z?%p^Xpo;&bd-!30^PdGAi3L>tC#DLZ4gGZ^{aN*2;mm(FinxA>p`Ri6fQs+i%$*7d zv#tdaoGLGZLmV~1W*QAhAw1ocpw~x!jAa^p^X7Bp_AV~tjsGCmqSt|kVj^oe+87)= zaWaTZUQQcJs~`$Z1(g-@)VYH#s;ViLA}7oufd(yEy{B$@1x-qZi#mD6h)AZoI@(D4 zS$8e!ar!<s!<R{KiDALLsqf$l=(r)pq({GWGd-we#a$w!gyKiE#bi#!%XV9j9Ene@ z<&dZ&w_)>UYj#=<D#%Og>T~FmD3xX;e&u?%{SUz4$Un^i*C{Vd4KM{200kxb(;UWb zPR0&4`c_irHkOWbf8Y9}Jw(O-ktZzVBCs29n>aImQWHuTI0Or>muv;M!~MX}Tusnf z?ETa(tqIkAL#lst{dPik;AuJx$AR%3b$1R1#6vpzN*mO-S2xiWfsk^8ToR9pUC+<` z<ymQ)m&nt&H+mxs<SIXa_fvix;~`!)lp@x2X==(+d78$#5e9}bvd7S2mDgAU+fmXL zJrYzYzCZhL<{ACWE*R?6iW)LJ85%@sr13%c!U}2q)AOyM%pUFv<`ha<^juKFe2eH# z_dt49G}cMw0enH@K>$7?cL91)E1WluHPZ@7j@RK70>7Pp29(?Ku3T#A(=&PKRtXxH zF_jvwY-(VYq&r))oP0HXj%!Rd`xG@Y$KLo7W5{b_dcraGCudn5K^`nAzHcU4{~pj5 z?o-<053n;iArKJRpSHFGp!5K1D;hgF{Q)}vw#`6mU~Y4&(QmQJkKj$k#ax|VEGM>_ zNRTRMo*ypmST$2j7-2{$1j_@08c7g#MwD2@5p=iCH(I?Y*h5(QEaF3;yER$W)Drb! zq&(4pt<glaa%RrrZtAp-*b;fQ%-}s7WnH~UH>J4N{B3(6YSj)8H%J(Q!m3Dg9c><i zAElsnUvq9&zk*v>qJn#Tk(*zLaeqMz{}R;r{JOF{rSC30>*m5YFrl`Ks+#JHqNH*T zn?O@X?XC7?bXkd7#J3yBMt;Mb9^iMws)pt96wKkF_A9VF%JPKAD6A{DqkJBzl?pJ} z?`n4g#weNh5!_hNwJ<;ruxr?%*1xYlz3P0u6hXRMNb|Fe{%SReymVM$20AI4j>=;a z1SfB30X9@<GZ)St5}^q7exUEgq_2R!ud~VRfS+*dibbE$P?O^vu15vP`YTJAt09hC z0#{RAxM7}{c8x~zI{aorYfwkL7>g}l#U*05RB`m)@@rs4HywlH?7^<}K2)daxNq~P zdb0ar1`-~g9x@(*vsdV`Z<FIkwLRqr&nJ<sJZl8qRsEY#VmEa`|AKt8hsh71g5 z1K`o02#3{u2P;r>u2+Gz73v4mVg{m4y<UfBJMwuBXhy?(2K?wRRbfu2OB#`am+4Lu z5VJq~pn%0|!@@D;%EN04q}HzFa?<qj1YE^v=yIjof*2ki)OD{Gt)OB<y?-No4_#br zO4oS6vNb#LK_n%o3PWEH=6%+hw!(3}l)9K08F<o<=k}c_mC`JzO#1RYp4Pars$uzH z|ICMgSH72nn=0okSWkB0&|@s`(94t_gC8=^a(ExK9gFCJZSU_nB6WYr>Rw#|f`9(` z#1QGM+mi%5F-!q184<v{1SETsbFj4oB!aMYF#b8-1V||P|B^icZf~yydC5UQvZoEu zH=!}lOry0=FxKFdo(=?R@?OwmYbsW=3BsMPo^vjhxXAd9U&c}$X~n;OR0iA7vywkT znF-4SYAQ3zzo+n+V%vfO{c2C+u5K<S4~<scxSA<EFQo*QBdr{054zNs*koKFGt=Lm zp>H(|jM5tKYDRZXS=e^{v2lb2J=Y7~O>`8A%1+B+#2y^xBtA?=j6&4t#dsW#05k*% z#mtl;n*8;alYacwJztenM!Bu!E?dUF)QSSk-U;8D0V}g4Jfkgk>ss--$J^tmG9>ui z<pYp$IEoa;W({MyZq}~#CJkqQqI>ILf@bUO$vP^*#j4~<^J%$vI4~^ZW&M)ec2(Cf zeCz|5F_R!Vp?Zi>{2XebD|L>qQ?2f|3j?_K&f}MK_M(Ck18KWP{rirhJCIi}qex!2 zEDirY=*g*lgO~wmfd~L!7~$_NP~Xn(|205B%lqq-mCz3uwFHDyfIh;7oJVKbkcaTA z$QMz0EY$&td#D<7qESi)3}KDs7^mWbox-}TtUC4K6*fhe$gC>blK5^fepJ}@T3xCN zPK$B{&6IIS@t^Bqwo$CRJwDz=o<O2hr98n!u>udzp4cI-598$*eosLRoeHHw9D;cu zzBpaROt>7c@UTQ)#B9@6OIf%zd-4Q^^L>t+Z>LTKkQstZ-*yyiL_P9?g{J%b$Ly2^ zI)qw8Btq2;l)1#i!r@_JE&Ws1f*vS-WWZrc-bG=5_9Q5NsX=*iFbC#@#4<<#ANmkW znT<KLu|Yz?usSrB_hiC@j3t-xa<#<t7D|=!40&kKLNly5{%RckxUa7d&-2UG+ktJr zIKG89yAAHheqq)fED8>*3)p*b$j~6FK(yIbi+rLUU~b&^_b~6z{Ti!)?c5wE7iFdB zx-WB{NXc7?_3^zK&S|R$$8{-#O0DtGh8t86B{=(hR-XdeN<>6g(<d$WSmk(cyU;pT zH(>C!WWJC-gl2u_tblxdPTu?36Zz*8Rqt*%?-p?6XEr?=z&F4p{kzxY_!qDJ@B4mv z=2p}75+Do+K+`&x_yc~$ncY;vMvbZzIBf(D2Dk~QHf<!xi~@Hay@FI+*q&6qqBCFU z(V%nGVAIpP#7oqr*Xy|wM-33_$}IFq$>&*N-r2CCkCgV2PvjL3>VcfX^jGk3o7F@o zwrds4h#H7MlITrx<k-ttFzYA;&jcwPF}SBsFu-z4G$#jcO?2>X9kl|V<&1sR;MX_- zt(&4v8S}NWRTdoJRfXai>1jRYOO`$N8YcxkqP1Sq8RJfwmp!DGe=y!M#*#vtp4y&i z=ov1Obo2Fo@M?Q=^Lp~|$ie2C-(z8d>azZ^PP_6exiRoN8o&_h|71e{?|9O`n*V>k z{v|KEoaBEi`0wDf|40IU+yEXjfA$Ri=nwoZ_<O+4FHuZDKOXQ;{yiGucj5mIVfZBq z1SAZ2^#X+dyzt*u{A(e8r?CIh6b192Li~f!{(EVDr~dxZk^u-s0+i-=BJl4Dey3sm zQXmUR8U;}Bi<I@d=<ht1U!vlee~SLjYWZEm?^KRo8o~fnX28Y&)5ZNevEz3wzmL%W z(sGaUhnD{VU4G`i`r{`2UBmCN^DhlXq<`1&3xxh%!_SEHze7F0G%!;AU4!8-;OBQ0 zzoQ?&R2WeIq2m7w3;A8)?~uVSg+72M*59rBe*qAFSNMB3{Fg#cKyW!g;s4et|6SSd zo!DQ>BIy25_V-8UzjSGT*Y|rz?U%kg`aksj)=i`PZTpXI+wV&M+i(7*5(uaZKnMAU z7yY~Ve>**Y7w2XDoA_TY(C^Z}zhZvL!*TqJh5q~#|8BKkFB~~ZPymwflfZ%k<ORqK zE5rG7>%ZgsIYB2ew*Y5-CioMr1T;6Je>^@;)io`#Kce{1-SAOA)f~1|Muy`QC8My_ zBO_B$xZ~7{b{bBdho#5kBEBPZrwkS(q;WUPyD5e*W}fC3dYXPyNDX3sLCj81ZsMAy zmNCE<thcUe_d1wlJILa2Z1Q{<?}pF}jbjwvPSNgBYM{Y*G78(yGv2_vfrec*z!?(q z6Nk~fgJFCc-!IM80>kDGLTn21nq=jlfaA!uLW!J2AN12ELdJ+}N6bguERYP`jtd~p zXB!xnC|9Bq1sZNa4HPTu=D;Gv*YNFq-kE}zee?KH{G*W#-SVdH2f8CExR=!ZE|eUy z($ZENHQ!Q{dzwZlP^(q_w>TWwO&%Lf40>8p4HxkjKu)fS;bMe+jt0#3p2zfwDbSFe zh=juaSA}VNt<tYL$ErY+i}u|fwO=b~ZYh8+z3b<KB5N9TuCh2--%DhGt*v>qYJ9!K zd|6=eT21c7((z9yX$-lz@176Al$&*0ytFA@K01CxB{%>2_3~Ds^JJc->s>I$@D7X9 zShaHZuuW<lV!x)S+nn>`?Kn<OK}7nY#I9iux+NkzK@%O&c)MTW(sm;x4zTW~&fD|w z$;Mk#i#$R^Tc%$cJ%dI?(qnPO4?17m1qC=zYy_jAM8e!^SaD9YYl@7^6mMy>W~Mk* zI$b<I5BulC)}4{qSo{}8T~BQr=pg}>^Rrmpx2Mzm+b^{nz24uWF~2mpSzC&-FPeD+ zpqt2p+8m$T{ZcY8x6FVSYA-*c(JJiA(GC%!dV#@rcDX&dLj)k?R5LN}!3+qDVGi-& zS#F{+`}+J&_}5}w%SO>iHy4ilMcwF%6k}lePV|d_T_O5$1*1JXXcxyd^s&JAhmV*e zJ3;&M&8=;RC%TV>gLoLrZv@L`z6}rT5%@9ereqNtLckihBF>(61bRteVA`M1HgE!A zN;C35X)qTHYLX-Qq^Cnb`C7Itw;MV`u$Es82;owE2J0hDMzA#Lf-1og7X3sppuWqx znIFEp9`%^fkBOcGM?k7#3xUZr_N|C1`rMgdHf83F%MI;FY<y-Z=o?s&QM@+eogjjA zRF*uBNqug8J%qg88Ilc&zzs6d(*QidXXkrd5Ej>5uNK=#W+ONR4yNJ~V&HHeJX1H2 zJaP9-QH=;|MWd*g&&<<;p4fsgF?|SvCwHc#-05blvf{eXA}Y%Pq^nx*J*viiU@)7M ztPSm`4Kzm2`~7w=m(#0BaxlY)`LCHbFir^PR!g_(GqzEm3~7>yDB-KqhosTWpC%SM zu;0;C8Re$$IE%8pbx&X-GlJt2yx-6iCAo8LnF7+Y_Gi`u15#ftaiS7tzAq*E&Q4KZ zE^kwWzcLRyoSZ=>cqI-xEpfDyqkBXQ6{Wht!=(46<Qv0#S;fQMy@ZADr0}g8^KL<K zGb6flPW{a5!P{62{B#l-kqP_0y0g342a$sN1##`<Mw3Jba-&7fksd%zZj*&g!tGzY zL?L!~cn9q=%PT^|0X*|afdzTNiH}l=a?A%4=52oO7Fx)+a*6TIgY}3~C@N9kv8v+I zTMDL;XU*5iw`TRtnT5h6&N#SVDJen#<-|k|STfL7Fy};lJwDp$EcRG{o;Umo3QY0D zOTrj=L{b5UbUVBWNizTWbCAefUjgC5L4zE=V{O>P*t_rTZ6_pA!foMkcoKXczC&N+ zw3l8-mD_e2Ea@mZ@L<bYk}z(SB#s8@lhej7Y%$$AGdY)w%4Qg3i+0=N^`wX!ePG*E zyHNkQJ*ljn{|P)Xg$HRPO_(VI!duFO(l4;h_{q!W5PpmrdE5=Xj^4k#+~^H)J5B>b zgy?IdO`rXEwO08Ak5AEVMse&HhhyRsBX%r-+=HkhZH82GhR-=j)LcfCVi&=K#FqH7 zM>GU5dtWDJ{e*^o%w`A)GxcX{*niNTiY>Tn`M^^EBr8bYE8j52?O%D9AY+0badcdB z^XkR)<nJ_FZo8Hkyemv<zOO~_{VVf9>~-fZQ`Kx&ZM}rTy+w^Bt%LSDjr}7up%9I> zR3RxQc3E*DXEPHu1mgsa5Yt5r`^l;vi^U#jeHoRq?O8MHG9N<x2I|5wiepJxge?t< zTO@jdIH_D=<f%ifrecJ~-Alr%OIO4RsswDSs$GRl`Lx~Yg5aui<z9{^tut3L_y9R~ z)VNK9i>}x5NaMqVCri)WJ3fu1l~gYz)bNVHNC~y>J~~w?x=V0}^_IB0$rp{{jVe~I zX2HglbM!2mQh76vW|@4=>*F<_MMvzZ*Y~TON_wT*w^<ss@@2_9wVU%22|k7DWn9S; ztL3fOJf$ysHkS3*!v_Oh5sUl2fcN1)dwGw>Gu-b1Jv;^gZbk?=<BxaZ|K{aX#Y;=R zXF%Y;2zVo$Tr1KP5Y9O3hd=C(RN+oZ%YMldHyIONez`a4m(bL>+_XpfzK-3X2Dctg z7xhhkT5c2*0w$$`mKkgPtE_4(0eiX}=0{+bsL?uVIyyAEL#grDwlfd3bR;#QOa<Rk zlvT8DeQ}-;FGa;0(me*&3N{x@ET!w^Q_*2>uq1G)`U>VDWoK9ep1U9DtP9SjSN^A^ zBXKh1E_YGP_5DQx62Y(UE6sIPzGO!aDV0v`=*?KKQ`oeNNIBSX`*CWs^C=#>GMkUR z4egZ`utzjhhactO3@<WwbhC41+Y?@A9DE!0ZHsN<j_y@)zMR?n_o16DQ52#&fL9?7 z7y$iGzGTP0p!1)=Pm|gjATklb7r*YU|MFTZGN}x{@F?#~u}A}~a|h2H60T#suz$f$ z$KdNdE(L`Qj)@r8&4>JRSKTfyyjY*7>w}V<HKt|98J)=)Y*SuCYYNKsb)8ARHIzs@ z-V;=7Dvih#?aA1x+_&fR5&U&L6&^*XrAN#%vnORmok>>-K>KT;bFIpM!Jer{>#L4~ zRlcOKO@&Q%eX@~{C@GAvb(>nS562zJjkOpW_M%%|C^MM3REW^AN=8!;KTAoqdS(+J zU0lKyW|Tk2{z_?RPoWOW8`iRMRg>GqvQYusw^p?K+RJLcF^{|f%u%~^E--p5u+4IA z?k^LOaLYqdR!#=)?#Xz{qj;nD1iOUSYNq7R?l5^=f3SOkvS|wSoZ$V+iMv&12$>Lj zdwG0v^8?=F2SwfJ8>=ZE#o_W|IYA=+OFhR~S*>p34sgddw)mc1z$Xy4z2g^aDw4JN zO*j${u=WhhiyPgghF8-Ry=z>YT{=PL#=#21h9HX&TEBq@h4<K(a2i6SKByMmsS2m7 z#|iRz-4N)4Wr!hAD67o{P^UGIF$>M+l*Uu!ZSHDo5-a>%Y2>0M2AUnU3$SZd$%lSN zIfBgGr%`o9;Bwz1cNdD|o+Hgrs~2%;{Mi|ZL%9uK1I33Y4yuOm)!jE1Zro<mvyB`N zV@AXcz8h}l&i4#OgP%Km{6IrUUHE_^B_=Pc)qyU-UeSB8s&FR#5o^~aS?j`Vq=At9 zrL)yw!Eykj*vF;UAeT_TY8z_BX{0h_AbubQ-5gdjGh)yJn!<umvUg%ccQcw-6q<R7 zmpId#?u)UyCeIW5+;tLXxjPa2H&BlSAulz;-O|eZ9y96Hgla+~7ReYWtaBfxs@L7* z71;9W1=rz29!WFz#l@zL;l~Qb&7Pk4q|7FGkil%<^G!j`iytc9Mo=rY{${s}J*ui* z#;H*o=krf@qWJj&vR@*eBk+cGU@=)}YeS(C?!L~3z=nIZ&DV$wJ0)Ly@by-lerE`v zn;No^<c;QiO|!SFj$r|*R<?W%9=5&(cIg+`krUfE@Au{C)3APEJCtA>i9wALMA4`J z!TU+-b3}&gB92Ft*M`b;aZe^g&l)2n82e4NB|D>5L}2*!^pBoY?Xo&Pe@t3XbcvQO z$smP-c5WB0u-mtZU8h5t1DKNT@uqj(KOjCn`lC*E>ZifwSlk4$$6$9D_Iky{O-3NF zMShytg&C9g<Hr8p06r>YuHXD#Eaq&5`&6_9n^#DTziurC{`ea@0vpct50rj92i!{A zv^<dIc!bdK1-2|i927bN0h@(=!KU~H%SBiPtJEtwfln%qAqb@qj#Nlo>Us<NgkPMi z)Gr|-p0Ccig}m7K!%@TK=-0lOis6vdJD2Jp#Syd+g6M~Ws0@h=H9v}ajb^ie4UsW4 z?1vVyk5?;;L=cQsJzaUjuYQTm?FjD{eR(HR@5~46FkqC${W)&*i??MrD5wmyrFJL> zQTi=NX!}Lm*GZ8Y<W*NJL^_CS`^b0O!GIn52w*DK_E3yp4@pM*%UK*DNw8ND7ez)j zz#+qyWW5vOm|H!vk%H=2_{<MCza0x;#gnv780qY*^N2Cw4}YaLf`jzt3gFpTr(oQG zJ;O7qPh2&O+Z&RtdK!cJ(&!my$ku#8MkcVWc|vm^pQzFOnJLTU>vf_j30>7~3OdP6 zm9jFsfXT&f@QM4~y5<kKmitzsfp{K1k<+03D?JW=J7PAf7peff$k1fG6O$=|_*oNT zj%@9d4a}4bL*fghb(tR_{nv3kqF<k;Kxon4PqQ`EKx5F8_OY*}fx~toPImN^e7`Gl z-HlVB>=NeXKAf%nNb2kFs>hZGF5aoHm8lkY5S`E!tlpV^_~O%;Q>5WG%^R>O|FGK4 zY|j~dP^UounpS@wk%Q+{rR}A0(jPjbGt5(peofaY@_2&q){tV!!%}a#;yifS+%AHC ztr7bq7D@4=qO6MvKU0(2U`fxdZxWp5*2LdaE6dESfM?s0EW@+F9eIjtW>lD%EQ4>x zOM11xjb;ni8{BcTY5u0V%+g+OVGq(*6e~avFK*+p0H@vZ8p&gzl40r_&w`x1$jF%M zgYc5lOFG@-gRVo_^lkle*7}Go*ofu&;QY6KMGZ&}eLhSW_scq}jlr#e<ou_lDWs@S z7ymH#04gRmp>@6nYe7$y=p_;fu$kU`$PpXiX`(Ulrc1j`>TM!dbeXgP5>!wT9MZR_ z1D8kGo3-A5br5)`XI`lQXrnkF#t{Hn{plc>TG=`}>N~j8{e4cAqLeSTb3doB5PODK zK3Df)k=Crv{+cpigBr->fZG~vG7_KN5{ZD65%MV*+2HxTP?ih6;C8M6?h{kpb)h+W z+U)5p_x*$S^X>I@;yt_!WDO0%4&E(SM13h0%dXI|$7@qzmk*0lrbKjTpDS<)?=d;z z_PD_PQR0iSX9UH8pU8Wt1CR%O={&D>9k9B>$pLyZORP{PVW16SJfoyJ@iuUZnM0#( zfg&0TM;1l4n<XfW;4sH}8~h*8eaR@`vJ*2}U@1gu?@q9?fYA!(vh+`3>YG!(QU^>z z5!4IKkrz~D%fm`nQ2HGw^9w5b8>te%7&=B<kTi-pRK!;im8(Z9k&`J<+hGytvXdnt zB18~oT7c9gy5~XJ0SVfk>eEGmDB2ofY(9{oqJ)>R_^X|N2Kh)lFS6vo1a(I4xZgVG z=8Q{M+?x2~CQ+o0@kv&&VISc_%Mc<`OD^|Im!9{axN?TwXU5U(d}(Tk&-*m*3wNC# zbUm?1$|wDecS|40*yUg8XQm~y!i1}c$HkU(m=pztQTL%$C8k6jq7z_A-lu``zb{CD z<uhbf3<0~wrsU8WtBki#P>jc+ldY0(h+RW(1l}}b3(7v)L|k5yr}x%c<~4P~+hxA6 z2N)lcX0K5XTt(wGQ#FB4X7UOKq<{@^i8tdh$)5o&LYQGunCI&@a$N7W+8!C}jJY)H zyJD&w2HIfane~T|ZvB`voF9G=qMpEZA2IVF({}8FfQ6YNw1?KqMCWQwLX>MyB1jK} z5DF-aXI_>Trl!{JuZ=#V=tZd|wFhL8y{xd3M7=|yN)kn5#EYf(+A_Ibbo^unhK6UX z8AuJGz=wj%9KD>unLUB>VQ!r@Tff(b-ELmx3&VVeA*RKJ9la7wA)ghdOz*m-#)ZPT zO3kc5Y)AcfeuUwZS?^_er?n=h>-1_P-{SHlypfhOeFp*si&H#?Bl9KL#sx9%F{o4a zs7p@hJ_+Tb^}5c-8)N6I>${!3+(!J_wjK@b?2VVluE)!>yYB|hFSqwkjqLj3YR}kK zHY77Sv250O@aMhWoxT81`=35|-G@GyGyo^q9uOt`&s*%jTuIdp#}#%2pWgH*e2kn} zJ#1_U#o4WoX0!e+$YhJA%V>F#)b1phg0GJ?B+!YUj!4?agd)2(&RZ*!T~r@#9tcaT zanTa&SZ$t6bvlF9$C(CLckb5C3Ye@~iv+2Kl9;${@awF6dwx9C%09&pN%&`20fQzM za^tqPN}v|nsFrAE5xakao&?fzj3)-oHJF=<Z=;Kp8NYr<k$@mEpO5XP)2lsmY2S%r zr6lj<kN`#dpkbbfs9P%@QHgI#sI#+}G3l<cpGL7$PemV$!Jeq8AU2ZHn+n@kO}zYK zj@+5W+1-87ZP4jS+fX=cIWPwnyh)LQ1V>&<%RgW-vc*(Tc)@h3Z9OCB-+qz4V7@!E z3K3um@`A$G6>X?y@6`W2Db&bz=Lp|jEL*Mjtw&D=g2V?~WOq9*v}--SsFuSJnns)` zt`1cR*DfcfhAj#@Ne%)Wt^?F`fpO;OO@HEXgu4F#6y<x&rZ=<?0=vlysI_Y|xBq4y z)8qqN&9(xBPQxh_aa=b99lI)O))ot8d54I2mD|>j!M?`bbbimaEM1VX*I~hUl$kbu zim<E-{97tzBIpP>Rjs&>pHT{~SMHEJ7W>uNEh;a}bZ6nJTslPF6(czB`GC=al*&lD zQUV9x6dILNO81tXN<q(2L58^X53kMcgUSyn;Jim4o(l}%l_zz%O*FEwG@Mu0G-w)B zOj?(W*mWu3ssfhuph94HsC!rF{UFDWAJb}7ZBrLeqfe0ZqAJl$0;8+nuv}s3QYpLs zU9783tKdD|g7|3t*=n6Yh=Y}@+vzY>j({PkqJWNXYO{c|QEB_b8e-__AfX<zUKJcl z!Y3suysIE%U43*A4C{~${Qlf`eNvvUaKlcX<d^S=M~NmIW9>~oTM3BQ6Ukw3XBg8{ z@=ju^*VY4pgHUt@G!O?|NatAh`y}bM>GKI-dZ@$KSb6a6NnAZ2%UKaFzFm+=Gq}p0 zz~E7&J4Iq2GJjOIMG%=GYKpgL679MsxZIZ(o4yX1I3C~?@zD3>t<CsiJ35~WGDu2t z{G`urCJ6Sr*|ogCR|eil097%`ClZ2e+hKOYlm$8{u<$OIDAAwq+9Mh;tSJ2@GtPW> zu$R<`_X;dfbhlyS{xkM<%cX|^yS4BDISh7VV;GqJm)$&1?kBIJTy?%6%_Fec@#<li zy>NoE=2`gqny+F*FG=*FWElHoydv9-_Ijm;z>ssXw40P%eI(3mOvW*bCeo^6Ru=0L zLd+8SP(C~k#d3LSUjE|hYEE==`q+Vr{*p@SNMPDLt`6#?^^FGfSF!{cog1zLyX7)p ze2Vg>r2@4JJW33{wnsXL>ys=9BQe|X*>E-5Dn~0Ko;(gwDWSAXCPwqwDDtRzS(j{5 z1(J0=h_MO;gMvX*oAAn2utBdZ6r_O4xD+fpHt5hmXH!=h$0v$3S6vu+)2s>_q9@gP z9<tk%?^()FZ0wv?e98^CLSoE9Y6H0<ls#7MOCKhWpMD4JMo&(Qa~IqHJlaK)WF8pT ziQSb$6wc)7y|y8N{_ieB;B@oeKEPF|24D(+Ea|_w41W#9{B0J?KPim~(vp8t8h_#n zC7lsrRvqYwcNMqbMsr8tC5dsEe2*8f0~YA1!$PswaMxY31es?ChYMV!c<(UPP(P59 zplA4VzNfq0S->SnlZ?LgpY98SSv~%4a2>QR!Mp7fR>c^+#7~EG(QLA~W7ZCVNMXAY zCrafml^yf7dj;;cgWA?PgDH>GphDY_;4H&Z?iS^W?{vB)a4>XpU6h1FKA+F-EsE&D zKC7P9nH<bSKR!H9HnJ)eWs46jbT@0jLLM}o`!i_If#WTk<kwdJq888CUNF8H0YQB4 zhU0(D5Ha#&9H<pwAVR=v0U3xK$k5r*$<|uU+KSHH$=Ldj!3}}}5+L$C0>DZC`==^S z050Gs$y(3@D1ufEp)c-GMLMI+L2(>NdIfVf2F%uW;Sf?wX8$GiLGeQ6qJb;O3=+G3 z3_4!qE4$f8h-iMK&X#j3kybqdlkiV!x6x_osS@L6CYPN1O+Y1UV*QpfhG`_xg)DVs zj@N$Fts?T{>vx}LQEnLdhCbfmC%*#^(U*I+J36&=Jx|hh=Y>g8Y@E}y6EsEq&eDP6 z=Kt{wIZG{GyN8ZkL~}xS>kbfa{LdHR3jBP?7NDNW0DEBk!ybR|x&D6{B`fYfq)?&h zwPwR(W*U15ag{@7tGdb)_He?Mz_Y068Q0oDnKgT|D{--n*ovLh^ak0zK$jGu9>O>Z zD(%v<zO9$DD2Y))losT~#)v>?yQ<vW3R)aaM3J!1m6A%NlCasw#e0{Hg;pQ$ss!jX zC1&oF<dj&g{be`|r(U&?G8(as#I5Jj`}CvidG&C1%c3B#*{Cu@y01ltf_(aFE}E69 z6C>qW4J5?;_Y!XQ2c_g{-F;ehmGSZHqg&iwbSIQ`$<Dy&_OGz*w72*wlJRxqHvk6u zr}_K`yz!6#e#8aE-)5P!aRwyA{+V^*Clqy>p>12pjuLXAn(>A}cs8unq<4)NK#H5p ztnSRxi8bZq<M&>Mf0&hV_hh4XN_93tbW^N-X{&^!<;x(){_U3XDxK~<38po}7X#5! ztTwhL#1dd=!;Tz_UL7>o8rE?KVWA}Yh|(2c)0M?gSzoVZcPF8gw8&uM{=D>7$-r{7 zJ@?}y4>aMlywjW^U{g%Zy?bC{PR;6VpcAf7LbzCc<h;dMpzISMrXh!D#u~xUcWY*Z zAGr{z{ZsIS!w%ehjr`UTG;<Gaut8Ay3j`rn$Q#+lXN*;7;)+3#)SJaxu#TkcW3V7w z#0^;zmPy+!ic+$~G&iY-m85Dg$jH%kA2i6qdTnO8fMw+I=ypgx!v~nNvw#iXC=(JR zE+B+q-jPN*4+v(Z=}YS?S`U`14sWnrF*?^q)zUhHTqyWrejf^e?PsQ=T;z}$(xJ}~ zv0uruE091=l!sl`p)`<8@K~b-#f_c#cy?6&ZJfAH@^Rrcv1sy{5fKA7Crp?bQCq>y z^9v_3k&;_i{p{B)E84>)ehVNg;4C0ls~;?b)fgUj-1!N}uH0BGrCyW?$oOn%PN#+! zi5$R2ZTJH<*Q0Q|MFmdY*;a4cR*87#SI$ibhR7@8eA9u-V}QB5Ocp;}GYOU-N|RjX zEGF4ENePPzP7>#j$X|i%%3i7M75@mkCtikV0^ib|W}M)F`tHkSbhE$Oh!A%v@NV0l zdJ;Z0uz0~;YcK5yr%<(BSiy|+Y8~yv057Ja-eXDikwb`80{3f3E4w>KQJW4jZVETt zTfAd<7S-ZDiS#k59cwy|zz?<0B$^zEk&@|2siom=u$U<f3^0cByK=irB=VmiU0VpI z^uhwu@{UacZUgS8zU6NAV7_sceMIgWpV+$LN=;20=iIwgYSfFD2s-SbkNDoHR;e0! z8*t0(dCBWZPa!I-iGC46lS0*@oLGmuzhOt4GyD*-dC-H}o+2nxryTDqEy9N(aN{Mg z-~MrE$N9!y1c(#rL%JzRiOQ_Vn0ogIa2(ZqoD-LfMo&w)cS89jPbLM9kCAXIl-d35 z(TAV9MZn1@t@XXQX4<<&Ofx90`@7Q*Nnb=vV>+9`UZym46lgVo9(s<gfu$xw_Xo05 z$0{^{e1W6ew=}0znBfiTfN*6$=>da5%Ox?X`B4e8srmK4d;WyR?{fc&rnmooQ?rp# zT^X7lJhq1Enu^%|kpK*O`pO6fO|K3}gd-5NP0%S26ob0Y)(Y5&>eL$el*7-C+m|v? zxfzIQHPq4chfp6XnPDAJASn4bCUqZb0XB7?9`Nf1njc!NkH*`!E?oB&@a>Bw4i7RI z9~={1P&$5SKeT@Jn?8F8>Z*2V^5Se0_rFg&;N*41u?6Ub!1(={==YD&fM5KWZ`qQz zyKRUg7r@_fgLprLVs_&DOzQDKukM6LXNS73Byu!<Xvwq`KNYj!+s7doB@;u~joXb= zbeQ}o!TLlasG!8QhqOQ$VUO1Tj?1R`m@Gm0jY!f$T-Vz>cc`Cc%Hh*oVgKdBIYFNJ zC~=AoJ}j?xx4R2F#P@(A#Bg_sSTJ~Ie6N?|Qoe`db7LLuA!c|Gf+=0ntr<Oel!;U> zF88)P$g$k(57NV_jyWHS5bzsMvV)A+D)$=W$Rri&FeBBk>X=s6*6_`wz6K8*IHJui za%+8Hrb&8{5j7OpHSf`z=qgxq&R@Ht)-d5Na;N3Y9{NB>NUd!cf(#^~mUfl(CGwzv zsY3+n!(?dZaV^O@(4CzhBG75*4c-X*d=##}xr18J&S@<NH6y!CGy@RFFyUQ=%PxHQ zsXS6oSDTExs7XBmBtED?+I!HHH}vY{H$b@gd984tD7TmNfe|Wt`*WJM$z$Pb(X0F5 z91;AvP6D^lsYH`xA2Ml-qfgep6+urv30;h%=p@~j8`g&x!Sf|E%>Cf{haeHFI%0Sa zp++SyZ^`Y#{<3dLzUsCZDw;CJo#WOXwP{6*3#=KuPs}W<uFO9g+*}@YY%;=yaAC#n ztURb;U7cJfe4_=_YWR{pd9WA=83^0V%RR4XvU~ToV53Wde{7r8QNe#;_33Dv#P|}_ z5(`GBa~Q3dQRj#z!p!0#g-%_Ni_ZL#G-uZMvdSir>mf9%TK>b+tFE>S<6vglTP#)K zY<o3n6xf>%)}Z}9!Wyn-(pS0vhMjeVjy#@%4ue;;Y`+kJ*gPJ)+uEcC?^gRPm~;9^ zIUKWl#rrd!1^>I;V}5X1=e)sE&bWbRHu$00u=P~Ipitm>Yn(`|8Jx(aX`ILuz@h|L zkfw1Y^9ngq*hL+w^&>V>xSK@s5l;;zn_3-PzaZLtJ5vn6c71}`{Ir&Hxz@IN-HGk$ z$?3Xd^JN`yYz*rQO{zwJaGbivjmmP?HPId@ER@GauBbx4f^!~zPS%atesLlmy|Kw0 zvc0W_*!;m6VuA26Z!UTRKlBgow8j%<(d%{C(j%H^5kmYpawP89z9_WHNk$@ChU^)R zDKjjET>mq8ti~j;Bg%C5u&EF2cb^K(cin$b7Ni!{!I?EsqA8F}3dxa?OuD_5*l*MD zbs4+A)hEPl8ljHNBLgOdK~SuEZT26yp@T&!@ioq)e}R5KXxbAZHpd;ERN{_BFMZ8y zW9;>a#rE?@#=iMC=IXaL?Rp{=ighh#n9kfzuIP4d$Bj;0MVD-(dZ0tTwL`~}{tsiL z&Y~%i{5i@tpEA5Z;T;5hgzry|<*=6i-dv+f=s@W)HLLsvTs`9zZaH;LQp@rsvF~fw zE0QN!%9w+{%Xw)|dX0%lp&4p<qFE`4PBQe$s|B&h8^kKaChUZREu+~dkFd>q2M(&W zBjRgojpbf_Y!zR1p3f3GnWgb~8kpCYpJcIkebr{Al8o89#ckbiuDP%th-D(9QtM45 ze2TPY#lM@5IS4qESQKLwJSpjFU&F7*8(+X_e+nx0d3L#@CZvXYt|s_gyWS03^Ftve z-9hgeNY+jMatK>77xH=8l=G=Q7Yr|wh~4{ge$`O6G!*4D$vw?T0x6a|euy!#cya=# z!fj(Z6q8JSH`FD4=DR5?=&f*8f{{8cC%2j8?l4!pFLzZ4%0()P;rFgMI(cn(f6P+Y z>xEM;tUFof3-`^v$>~t#{Lg$9#Wf9gp(njkWm}JQh)Hb2Hv~J2LZ+5&ui4dGUe0&S zr0$=qQsuJUdpb0)yzX0luS(sy_m{m;pRoI&4y{3`@>&UZuPDVGb9q#_V{uiuH(qWr z7$Xk0lCrj6hz#S|Ov%&eWC05sV8JI(Qw6_y3yuLkd1JzT|Mjhv^TXsEQlH;L1XJx? zZ)qhr*raL}MOrPpBE7DCiC)jP)iY<_b-NnKQ>Fn-QEeJi+$(8DQ{GsDDT(K05O?Ge z%avU~Q<1ib7wtvwruhT04ZN6p4Ch_j60Lnt)^qyjE*9wqua=2HOnIb{EKknXmUO!$ z<Cj*;)ya8ljP6W3%)~faH=LQtS+dURveZ&Zq~p1pO$Xi5xg6W&+X9G^$lGNf<i_64 zg$BwcOOsXjCFcF7g={iulMAyU74Zc*H>Tm&w$A#9!;CAV&MT7-@{Qk4%phaid)FKq zC2G|1oSK40xKGW>oirM)<_0Yj)|kNt1T>$kEV(5wahpVDR@$!Wto@r>tf2Y>TgWTK zKd{3Ixi<rOlxCWo-mMK8wvLpI%Jh$p$sAQtaTQ4G;UCc?GI5cbSL{^#@&JGD(GYeW z&)TSQb6@Xq=`Vkh)<!qjO4?^O+l}hfZL2WGd}4QzVRI2a=ra81B*X6_Tq<S6^0AnN ztJu+|ftZtwg6my&^=6dcgvvBtYIR<>WJ>@_s?~xas@_K@9k?Y#vwT4ijWQk;C>Ick zvc7NPWpM#$l)`zzP=F%?pcpb`(|BY`W*0<CV)lrXMSt%9DS_bs$7#oHEv*?`kf;jN zg250?a)j?_l$v!;36;!Zktv&80TOKxe?Jz+4~<In^VB2&YL+NR2uh>$*De}c7AJJd zrV&Wgl}><&RuB}$pGEuYLO;tR_|GC%L<aK&L7mwP2H(*N2BV<o3qt*;Y=4UU+(e?J zcSZV7>4i1DjwO>?a+l$+OnIt%mo9vcB-oA%-Kko`v0OhYS2r|vY(&}(JV;Nw?QE$n zV6PEap)u9S$ZOJ8W@_CgLd*w$fiFFC{gHN)1Ft=MFIZ+-0>pb{0r|OHYDI9p2}ESQ zh-Ow=vhFym$yj#|Nh&b0rKr+L{e@ga>SJFU%@oEbp-6Yl7S_ovgw{Q?L4+7PO%qm_ zEuhvt!$CW`xUq-&Tb&X672UTU6oi$583LRoNNasaZ{=b`@~9fX3;-P-Ut|uCMY(|Y zWU0U|)VQF|^tr~T7UWFSR6C&;WcoU=kg~L3>CbCI$W2v+k}@mx4Tb>w>S|nMKf44Z zRsw%oTR_-5wFq-?WXT$@s|f+Asw4zHInF_DK;1b9>~>)hZg0n;J^#-k3o$zfmcF)5 ztb#0USb3WoFlEM-g*ZQF77{&eSV)-~Fbr3~g&HdfE2b8XsU@Zs$l<Z~+eFgz!!qMw zg|r-4VQ?!x46f8`FhayEAl)eMIchZ<aZUkh!NZkbiG2o=#8-{cWq3y36naL^rn*y6 zO!_}nQKeDWj;>76_|NLJ=999d^q;H0DrCQ)P+9rcDq(G*&7yqlZz~=$BPu|R0ecq! ztFdznt>*dN|5_P2v(#u<{AbnBiKR-z(*9qo-wLq~iM+psC^r{mB(izoZht_ci&FG9 z2+3EBIpyvpS=eW*x>4ZK?x^bdl5A9oz8U@k&0z8!^6=A{g!}`D8mtnR4g`|CZCye% z#EoX>O=P8#=54aZ?R|q6?lNxVkL)gQt{r>h0->AEx)u7JVL>+e^s_@^8}pqGWufVc zsgt_-d=ufQL2wSAV@(Ac={-f1lT4#crOc3y>`eZeo*4y}&dfb(jeA?y3#Xgy)245d z@I$c06ZhMG7MafkT^}89Dd=o#QTLf1h8QSq5foib;@t(9+(mS~6TUbiDR9ckBFEwL z*6c>^j8<&!#k)OBmbSLu#@C2CzeKdDbC8zq%}lwrDyQbK(b=wAEq8TQe>3R{gx#x( zUr^^1XXmhNno@U`wz}Flv~zMRfYp9xTVZ=C<x76egi&@m-S3rXbADs#-H!EI{2syg zP<)H(%Q7)V^}4&CcuVzqEYJuUclGG)n+ZhGY7HM}M@U36A6wUGoTZIGmr|;z`CO~m zM=H)58rYp2oVB;20Wl|ghUwPQHh<MztzUrI*yhyrV}~eN-=kC)R*jXuV=(|>BX^eF z=i_+y!)%YG)PaJGE8|po(D%b9^@k$qO7D^sBb7dxZic;)J3aD^?tEV=BW#N_?uwCz zTb#WZ0jwGa25Jj1?{6)HF!R1IM{Io0d-n#wPhWc9&YyZ;nmM|ap;;aGmlGyV6Q^Q{ z1``=DAe*(meS=?PM`)3Wb$)+#<iVH~<$9~bsmxfM*zRT0EHz&`5Z<2kL5aGSEixws zdE_qn<03tV`k-DA?E7qWt`L6?(-&P?luY(azkD!wPIK&&&&vh8(}QD|Rz-!<@J{5= zc^0vQ+7G&Pz-KHq@xu3-L58AmGau@^Lt*Enx>M=k?npyNSfpuW3m7|<90OOBdpZR9 zj&3Jr^1L8Y)ew{i<b)d4_r&teqtaBBQHfrw)fzmgv%7ZNwW!XHbmg(0%F<1{C$`*F zZ<RmOXQY-IxeqVwbycu^FjBNT+`$;o?Q}q{6Vjf`1lF_>0<)5AA=snxmzI6IJn;2; z8`&^$1fAh~Y4ZGbu2aj?DtrTcSn5-%wHWqQ`aAZ_+aN*`bRE7B5FRV&X0PuHxD(K^ zqnRw8--7N#<r@HW`zM~X5`zdN3_zL~0K>mObJhIO8+0``_@B7opNLY{?3yJY1Rv<~ zzW+5e!Bsk$LZNB^Bc{Jc5C4Lp+d?e?T3qYw^--J48BX_9XGJUX$v*X)Qx6O00|-9K zN*3%Rg=C)ub&~ep>6!CPW*v#JK6L(!;Aaa6E8fnoG!=Ew3G}ddmyjS7Y(`?omY5mi zEbw+PVnKXdwMX>=HX?;X)o&1Q_4YjBpTf&hBr4Ue^)q6YW3CR!)lwt|V8^3@u~)s$ z1rozptCFETt2sYbPNRP=3_>WwFZAUmPU4{ttVA9qKVs0se43xEDM%@}5m>2-dIc3- z^V@=?PpLaIk#YemoizN2x|Vg-FFzcA-D?oz2ecM8(-R|?Swc+Q*qJOsmy$u!Q5Y1% zVZOC5zQ9`RBED+M+<aKTcnpnpSj(dV%x%j%cQ`M5_p;R!9rRU=hi_e>?+xbh6#L(- z-dneI0trCQ*#Vp~r2nzHiLH&3lD>h}AEB(@5@u{N=>aGn*%@x!1vU)GxSaSxNi?(h z@$kHOr*jmr<&tPiB6DnA=rZ)FN$lL>VLv|_OE#Jd2ZG+~&UN<AMo)(iQgo~FiroiC zlu7#UX+;&A4dXMZBMTxC+=k)QVud6VGdY+}-EME^7OBY+8ao0#%;|X?71h>E8*EJ` z0cq(L=|OtsO$2B@&U?@Wz1Azx6~dC#y4NAA-S`GsdBBBV^2-`_lh!CY5T!IyFD$<T z$%`vqe~oHd<7mpB6{$ou{?wNtGItHK_1zD0pNyctTtzh51uPPi(}7$Jz79KlpN${~ z3_=zN(pYv5<EZbF@H%ZU(mZRoZ)+IwU?YR$9R@2bVyt&s_n``j*<F2tM56P1k|knz zt2>-FPrwXABe4392JE%#w28v}1J|(^U-*1EvYGFInIWvj6AQUWD{HgFc3t~Z#EjMG z!R%YRAwRJPT-e<sn@cz8YXh?}NPD!C1h75Hf55H;qit=%+oPH3()@_e*cH(Csmeaa zCJzP9R<%qu07vA=!MR;)4MqZjr=3a+>;o2R6jv}O-1Fp?J<c(ED2LqK#S{m_Q9QIs z7kJAxFBNc1m$eu~h%kG|JBBD?Zr{1Mo>@zwrX3mk-5#c0ALrdsq@)Sv9`7@V*Gu$| zeN8!zJ;X2dSG-phExvU-zP$K@ebhStdb`Sp5@&(~BCAB4|4bYE$L;zbrp7N6rz>0A zahn}2<f7H$EikfjEz*eqA;C%7gEG!2F+;}HM9fwfS`$RtDzaIccYm>#WL3|BdWSey zTzbI?D0d`5r+b9+)lb*QJ6iA}ovb|W%H8&|eB;{fbb@~<_MjUdei6Kshi*y@r%vwE zbJzW+x%FDz*N0eL9p2Jq%~3^J;O!g7-Q4>W^_E93x3ot|y!x9&tt&O}wm9)2##=^r z?kKhIO**(g7&YppCPl~_S_cb#e7{lAi(^M<Q3rjYEAEYP%S!(-7!(>ozT-rpVlM7! zF60?6UMErXWlqVN6UtF%NVuyXMidAIk}tko%P3dLGy)AX2@3yaN>{!O6lVwMBM|-F z167Q@20fgzQ8Mv69Mi6?u)G0#ODWJe2b}FTtB;RpM|dKy2dg7$q*i#83A3Y$gQu8v zue}!4uOrXptZxORRs=7SJ$fhflD8APyc9ZUwUc~{jGq-Q_LwBS3GtLVQMi#T_}I|x zDLsynKhK^Lp;kR^DPQHhdX=+PMc>R-eZLb1DR3=weH=<u^M0NjxL%ikRe4<8j~00N ztkg>7Tf0PQbY=K}7Ypw*S#id7@zTtl<}+tIwNUfflbRz<`>=1Yp!1<OSwPKNXHT;m zo57gDxJ~`s^Oi!_EBO@}-X#5Tvukm&Q^EGNty?xoDyj90r>W_1CKFybHX;ajjTHu+ zNS`mQ`!n%g|J}<*Z8Tpbn^$|x!p2}?y*z_dV5MqqZPV&PDZ||RM``dNkCW!5^KU_K zwLz#mYS_KIQl;Fsmw5Uav4S{9VNJ8E9{Z2l8&fJ}xUhT{9}8nwX0AS-nLW#MaXysc zX8X*?!0caqiw}GMnt_dY4kmYRPi-UYNNpnINUbC2NUb8^NG-$fNR5m;RX=ISJi;iA zm?ibtqOO*HDl}nbyMN9n+Gc-`kMynWDHh1)+Y97IbSGbLr~Q4YBis4w>Di~X+^VZ@ zUgdjhl$pcorl~YVlLqPbbUU?c=F}?Gir}-CHv+L_B-tc=yXn>J2(Bd$lU?h4LQ&#t zu?Ok2)7<TsXxsMLmrag??$47#%A=mt5Gb(-X_r>nYNA8NGGt!;$aqg#4hC}qLWquZ zIv*Va+S?6cji~X!hXz%V#1jTg1RI@O=1CDj5;+Zgh&tJ%85^E2m5bI!B!s%gIAJ&t zPq3#@n5xd3{rjEhU|~u;jrHi)paUaJl!TO~0hv(q5Mk8>h_PC|d=#QJfBpy%WwrsW zern?hqh_Y)={Uw{;&Ww#E#`IHXvbx`!eD9!I`nCy_?+%>PpuydsY%1*t<sLCdB)_z zhm6_f4v#X@1RHLlZCf&`bgMCRa{j(UsE~0n<fBn7Z0x8WwvKD$TDft9PTtz|JX7N> zcO^?TVKd`dRPc$H!0MVc^$G7_3s@VPxP(cd2X#NpYe{OOhD^j{tF`fch_(8f^(`+| zJZmjKQWIm+E3!0JkGtlTaI&#%w)i3=%pNrSVOS$|{DW4d#_Ooq?D%)p8H+ImeT!mT z;U^()_o<Ce!^+RN9q{R4=1!fQVQCON9jHT7gKMf60yR$Q<=`P;?D6WP#Ed5Pq?fvU z56>ISuw8N@cF&^otI!2=LSU?@AmHg)B=3n5G)yAY;&6muFW6pLQ>h`%%<dt-0H)ex zN3{P`pxkpvaG5e5Nk{pHP!$4m(Myf^*oBZ>jwhy<JQs50@k(~zS=wPcOU%J^<DH#; z9cxl<S#V^xmI}$$b}k80Si;GD_#ipGjH`A3`FyjClM7Zo1M1|1k}00Dt0bPYZzsAh zsB8$MdX-QIFtxuCvD&+_5V?>Oav2IwE4LtAR_^0hBpJ*>V)hTFZg1kk{G=iN@)Y`d zN{kp7$zWijl>GNxPLy@$tw&0FYZnV+`ofZaP*D~+@p!M{HQ$x=l&&ZH%J$R!<)@h5 z7iO3aO2*QmSs+TehLsbP?`wgIyXJ*6;Z++AB(M?fDv#o0_CwBQx#W%p`@9N%dXWAG zBIX^#Nup(Sz)l(O`<+95jybYH8^lyt9YaFg$;R5Vk0HMEzUB;?DOTUfX25&Yt0zgn z5BdMJcjfU=b$^(WrI%8ck)0A*iWX~S31i8i1!b$4Vl-JABeGVbvXv;2u||!dG^CQU z@2`3_V;czx$<ky^w%;*m#<aZe@Bhx{<KuJZ-sidJoH_T-{XXY>pKF{r@F>GBA?vn% zd^%gq)KTpCw5(`MtcvxSSL2pSU9<112*=tvS_@0_mBeC96G)i0FIt(Ygk;L`kT2PO z*|GH+#i=vJtvAbHAKYsVp1%GvTQw-_Ej@e}zUghRbFD!a5nHuc(}wT?hn9@rS(j)M zek#^i+9bz`$L4u!`qkX4nRhPCZ&u2_!+h??uQJ1;6CPDQ*>P=;XqTkMDhFwew8swz zu57+IQ=Ev|OK`Z6-qPMP#BqJ1PBQ;+&$OSy$jG<`B%Z8E^2GDQ+-qJOeU&|f!DHne z#3~#6Dk7Y)UISMeIjSO@ZeGpoydUj&FZY!RTDN}_9GaBFw_CD<z!z2tmlODWBTKwo z%G%RvRr9*6n3ZT2GLSQr5tnaX5DD5Y%kH%us2brw=t$K8d)%0VcgTiSZs4nUE&wEy zFd(5&KL-dP=}-?-e=wNU3Dd{$=9){aKmzeas38-gA;4GB6}Gy|79h6L?*m$mK9F_5 zq3}c8Lym_Gw1t*F8i8`Pg|F^%*T;OBhd@$wR#U6CbfWqCaQ|4vo)gE}QcKRon;$O- zHJ2za2XfQ*x-CHFH^Ww!U}?3l->Df2^qSTIwy!w}jT+;v_W81cW6&}4Az4JT=;6GY zSBN?J65Sf<hvUVi$v73VcG+&;H}NTXHWm*(>J--9|0}WmUY+UJLwzEJDBL;z5}O^X zDCVsOZZJ4$XE#1FsY+;9-6&#{m1jg8!FAVqVOFS#VbfPa!4^G{2rajRaX6N>@|`9v z`RmtQe!2x}xuTO@1>R#MF5HpsYs0a79OdCJ=J(bkzT(c5F>|uBx&^y5T8Ef>>FCWq z0m0NPC$x_B*ubT{?PLy_JwWEjM)Mv8f{h8nX-6h$NdGZU_JMsDqDV|#TX*TI83TFc zKxx^Pn?SEQ@Lc+oMzJ9x&^-nSFKNLtD!9&MPB|dDqyfo>B(k>3BJ4SdyIUT}HHKUe zFDsk`^Wt7<9CL*&P;zbwro6oi)S9CRgCZj?4sZk=-~G+Fx+BpdIP=w(CGMfwM&d(( zHXLPAy+%p<9v`}j&b%edQi<R|97aUoZ)K#ka3C9Uc*r$Q(n+JaCnzOkb0-WCYj8k! z!7etVD?<uT0y>NNyt*O-G!=p|kZwNR1%i#|QezhPAfkc1(vn8q1LPj{1)9YsEmAnf zfMXgAX%xTZUu3y)c<JQSQ?%i@wJCgNIaj1&p%Z@YD)P1`GpAyBX0Pxh)KFsCM3I(- zDL&p`2_qwxaY%nAQ)D7eiP#=!=WVm4s*pL4DUQpP?`o`l_M31@i2b0f|I?b>$4?Kq z%-VHpLdPXnOs0sn!yK)Gc@K`77Wz7D&4JhJ@}R8-*5%dPXXt+`kFjeZH?xK3`X**M zSD+JaSwl90_bvE7$7<JEyEwzs{pv|2L2!Yy&=#_%#oa4@TnFoJU!J7kHP3WuG24ZR z@ze?l6cB{d_9hN17C1~cdcfOveh8JHL;a&-??f3I@t$q-ZTwoc$z86)?TON4ZBO;} z0P6sEuOQ_8YlvX-+nzU`(bljxNaNrnsg6ejzT&auVlN~*XPw-@oBT9G+1&Tf8ooiA zq${INl)jf<;fH-ts{ot&R;Uv+3>}jfX|3j-RX^-=$8p&IpKHN0IkiN5PQ9a>y84T~ zal)psYY&5o#q}uP-GcTPgPMi1?>PjR5}aGxh_grL22Lod3GROgjq2-e89kw%utvYM zKPo4x{sS+{%eCk->dCa+%y7U@g9okRxi4xU*53$XeUYW8^Ly~{L(p$;N)7tGcnVA3 zczqNnT*qji;H-c+r1%HEX-j%EsPN)_k?CjTiWBFKzZ{*L@n}NlHLKn6)e*n=k~{Ud z?0SlzaaR-OT!8hObjjrVzBqXwnKDrW`JN{#Ih$RNjjdK1HZ-#O60Ko-#U#vgt5hGC zs@}fL;*pb>Vq6t5`xXpy4Y}u^j|jfH8Y`X&kNEUhRmD!hRrngGb6PJvI~*X}R$B4b z6Dvq4Qk+XJ>%JpwB(1VB)u}Eu`1I8cZMIskJ_cSoEbO6lIZQpI6zZ(vF%G#sy0QYI zm43YG^=(nk>d4-REmLYO)k@v5BZZEym@fF2eYnjwXlorwoFtMR%;aj<7n+we#iQI> zJ@SxET$5kp0~8wTRYz7Cb51Y|T@Y`D!xfaby#_N&0WZg=|25JF2QaLY`xEm23Hkpm z<S%9Kmq&rCcIc1m8MuCaQ^Ic8f;$$F%uJ@&8h?gru(QM<HzA(hDANtAcup2gB0M&+ z7MPkq3kkuVQHFdAdi(lXH-{dKWP>VN$i${N>6$U!*s}G5vfjgfxGFTr^N>fJ9LJW7 zq7*&!`6xw^9q^788LkSB>>z1Fp&i&1>{<1SW`YPWDWX8<TaSM11@*)@g~sT?K7PvW z>l?NfnZrcNcPWzgtiwjej~VzWdavx@+_z?x!72BhAr!s-BHr;&TExj@`AhhnHaF3A zc7B8u$St^<taLc(vsmXu1JU?wgIN_>j#b83H5BWn=E(8#(q6*l*V~RgP?)%SEtdIH zboFjS)^{#2ygsqPrE<dTW{q3_J+{~w_w2vf2d6di2DFRuXAx~RngjYwg%5)(r;$xO ztPv@*kQNl#;M;Ds=WmBtcT<MSvSMs|k;9ayb}6U#S8NJ1P<?65v);5<NkVMQ=i=mF z*{ZITweK%wR?8<$OQHiClRMYe{oLO5Q-jm6D;TPkV5t7FNBi|qjXzKeD^=t!*!X3w z`4Gtv!>wa&d7tlnkugH%RPDP>{1M2Obi`Z&m-D_rp}m8D`#^WNlzOzsp1v%BI0f-m zlN;vDLK(H5j4ZV9f;4&aM`arcoN|v8Q|vMJ_h;Q!?9FND@V7xph2FdL53T~CgmPHf zhQ|t?2#9(ldvNfx{KoZ7Fn^R2&mBlPU#XuC-pux^xuO`aE4r^RrKb9w{aXt*Qy*d3 zfr51$lLs}OPu8TZX|B@gzM*(?=z7eE3nGl$PWNJDOi}QPcQ$5`5b)n3i(O|kS-g-% zS=+7uMg4(IWcdKn_NN~|Mehk{sr%-9j3}qIPFY6t0_?I~!0Jxz*5Y!r>v-`vao_W~ z%970n$KCWgy%qNB9&2aGwCTl2sVQ6Boe;J6>u#J8jo7GJZCIv)C5J=S2Vk(2Yzcn8 zXJTAoEN_WtS%`RICejQ$G>shXZ(TEYBgQi4!mFm2FyS;&P0l&6PWHzc50s{wPYL*L zWWYcb1s;C11=$O$*1s>yrY>3kV=1{XjKf|(3IP_?tQ|8Q?~0vV<KLRqth;Bt1*KuM zCSMS0xZk1H3gO)TvL{^*^-<>P+?4tA7Z^QTrJQ?CNjQX=fC$%K7_0x(3}R(Sc}4M7 z-ufbu4S8+7(DP;GMjT%Tc<?E@%8H?PU9(#11mrEF6>rrVs99}sNI(&WPD_*QJzq3V z7BaU*;nrLX@)Zy?o7vN;p&Xv-^>m{bhd{R;1`Xj~eJ^|3Q8ql|iMNhY$Ewoy3|t6D zzRMUfpbb3jE{uZZ#%tOzuDW3`26Di%{rUF|FE9VWxlJ@u@X2R@f`Pjo;GipVVBjqb zrk|RoNnr-HS%800BCryecN3r$W8mCImGtRzE*Tw_cDPaG<_-H!fypCa4Mtb|!OQ>^ z{)_wzMkbXfJ=wmX_8GwQZGIYxR(OH$8kOm!t1Ie^D+*41pC2P0*UyxH9^mf+{PKnr zflVqNe#Y^a@S{7&`L)@Zn2rD!Dqzz_R}f$-k_!J%rf1thcb9-9l;s@lpl|3oes6m= z3eG<7a1WuY1(;@$SkCc-@fm11wMZ}pM(|-fG?|#@|A3DeT{$DU)E8itzM~`6ZP~=x z!Nc{e>q(To-Z=;OX?x2hhxo1MPM<x;*w2inRy6Xs6N}vc=8(te0YamA;Jmzz3uA}c z@$}YP%P$^ALkt=n1+hp+pVP?LAjX7a8vM2UBK&(?`nyYkF{_fsvmH#3QNR7~Jin_C zV>T0wXN3<V&wsqOmgoJ@2!Y}Gd8VIb0WtQ`@<bVW0u5hA0$SP(BMW1`2#v?bZ?R>| zvPT&4jH|_I_=2ECJZ;vI5zM%_fCjF)wg_fW9T*uHC(3CIT9Jzk%VKCoJmY*R4euSb zh^Gw@l=tbM-{%;G6B<iiA|uQH(V%%ffL3Ia8L58TvgKhRjfRQobSj-I-;y;pW5+Ci tRHuhS(&^y8F!fvh3`LJFxKBSe7p|4%PgF}Te!}3#>k9b2E6JG0{}02RC)5A{ literal 0 HcmV?d00001 From cd07a0500249873c514d793787c1163177606c60 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Fri, 30 Oct 2020 16:39:11 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E4=BC=98=E5=8C=96MoveSecondChartSeries?= =?UTF-8?q?=E5=90=8E=E4=BF=AE=E6=94=B9=E6=97=A7series=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ChartUpdater.cs | 50 ++++++++++++++++++- .../ChartUpdater01/ChartUpdater01.cs | 25 ++-------- .../ChartUpdater01/ChartUpdater01.csproj | 4 +- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/OpenXmlPowerTools/ChartUpdater.cs b/OpenXmlPowerTools/ChartUpdater.cs index 79b0f74b..19749e63 100644 --- a/OpenXmlPowerTools/ChartUpdater.cs +++ b/OpenXmlPowerTools/ChartUpdater.cs @@ -58,6 +58,14 @@ public class ChartData public string[] CategoryNames; public double[][] Values; + + /// <summary> + /// 组合图表中,第二个图表的序列索引 + /// 这些序列数据会被复制到第二个图表的序列中 + /// </summary> + public int[] SecondChartSeriesIndex; + + public XName SecondChartType; } public class ChartUpdater @@ -95,6 +103,46 @@ public static void UpdateChart(ChartPart chartPart, ChartData chartData) } UpdateSeries(chartPart, chartData); + MoveSecondChartSeries(chartPart, chartData); + } + + /// <summary> + /// 移动第二图表的序列数据 + /// </summary> + /// <param name="chartPart"></param> + /// <param name="chartData"></param> + private static void MoveSecondChartSeries(ChartPart chartPart, ChartData chartData) + { + if (chartData.SecondChartType == null) + { + return; + } + + if (chartData.SecondChartSeriesIndex != null && chartData.SecondChartSeriesIndex.Length == 0) + { + return; + } + + XDocument cpXDoc = chartPart.GetXDocument(); + XElement root = cpXDoc.Root; + + // 根据配置得到序列 + var series = chartData.SecondChartSeriesIndex.Select(x => + root.Descendants(C.ser).ElementAt(x) + ).ToList(); + + var firstParent = series.First().Parent; + + var chart = root.Descendants(chartData.SecondChartType).FirstOrDefault(); + + var firstSeries = chart.Descendants(C.ser).FirstOrDefault(); + firstSeries.Parent.Elements(C.ser).Skip(1).Remove(); + + firstSeries.ReplaceWith(series); + + // 删除旧series + series.Remove(); + chartPart.PutXDocument(); } private static Dictionary<int, string> FormatCodes = new Dictionary<int, string>() @@ -427,7 +475,7 @@ private static void UpdateEmbeddedWorkbook(ChartPart chartPart, ChartData chartD var firstRow = new XElement(S.row, new XAttribute("r", "1"), new XAttribute("spans", string.Format("1:{0}", chartData.SeriesNames.Length + 1)), - new [] { new XElement(S.c, + new[] { new XElement(S.c, new XAttribute("r", "A1"), new XAttribute("t", "str"), new XElement(S.v, diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs index b3e73ee3..cf4a2027 100644 --- a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs +++ b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.cs @@ -25,9 +25,10 @@ private static void TowTypeChartExample() using (var wDoc = WordprocessingDocument.Open(fi.FullName, true)) { - var chart2Data = new ChartData + var chart1Data = new ChartData { - ChartType = C.lineChart, + SecondChartType = C.lineChart, + SecondChartSeriesIndex = new[] { 1 }, SeriesNames = new[] { "平仓手数", "平仓盈亏-逐笔对冲", @@ -48,26 +49,6 @@ private static void TowTypeChartExample() }, }, }; - ChartUpdater.UpdateChart(wDoc, "towTypeChart", chart2Data); - - var chart1Data = new ChartData - { - SeriesNames = new[] { - "平仓手数", - }, - CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "1:0天", - "1:1天", - "1:2天", - "1:3天", - }, - Values = new double[][] { - new double[] { - 100, 310, 220, 450, - }, - }, - }; ChartUpdater.UpdateChart(wDoc, "towTypeChart", chart1Data); } } diff --git a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj index b36deab2..5bd48a12 100644 --- a/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj +++ b/OpenXmlPowerToolsExamples/ChartUpdater01/ChartUpdater01.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFrameworks>net45;net46;netcoreapp2.0</TargetFrameworks> @@ -15,7 +15,7 @@ <ItemGroup> <None Update="TowTypeChart.docx"> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup> </Project> \ No newline at end of file From 691d2f26fd7e98abc7617ba3652ee11799dfa4ed Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Fri, 30 Oct 2020 17:10:04 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=89=93=E5=8C=85?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ChartUpdater.cs | 10 +++++----- OpenXmlPowerTools/NugetPush.bat | 2 +- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 7 ++++++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/OpenXmlPowerTools/ChartUpdater.cs b/OpenXmlPowerTools/ChartUpdater.cs index 19749e63..61003cb7 100644 --- a/OpenXmlPowerTools/ChartUpdater.cs +++ b/OpenXmlPowerTools/ChartUpdater.cs @@ -60,8 +60,8 @@ public class ChartData public double[][] Values; /// <summary> - /// 组合图表中,第二个图表的序列索引 - /// 这些序列数据会被复制到第二个图表的序列中 + /// 组合图表中,第二个图表的序列索引. + /// 这些序列数据会被复制到第二个图表的序列中. /// </summary> public int[] SecondChartSeriesIndex; @@ -107,10 +107,10 @@ public static void UpdateChart(ChartPart chartPart, ChartData chartData) } /// <summary> - /// 移动第二图表的序列数据 + /// 移动第二图表的序列数据. /// </summary> - /// <param name="chartPart"></param> - /// <param name="chartData"></param> + /// <param name="chartPart">图表部件.</param> + /// <param name="chartData">图表数据.</param> private static void MoveSecondChartSeries(ChartPart chartPart, ChartData chartData) { if (chartData.SecondChartType == null) diff --git a/OpenXmlPowerTools/NugetPush.bat b/OpenXmlPowerTools/NugetPush.bat index bb653544..b9cf2dc8 100644 --- a/OpenXmlPowerTools/NugetPush.bat +++ b/OpenXmlPowerTools/NugetPush.bat @@ -1,2 +1,2 @@ -nuget push bin\Release\*.nupkg -ApiKey 123.123a -Source http://nuget.cefcfco.com +nuget push C:\Work\github\Open-Xml-PowerTools\OpenXmlPowerTools\bin\Release\*.nupkg -ApiKey 123.123a -Source http://nuget.cefcfco.com pause diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index e3398957..60b12d05 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,10 +1,11 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net45;net46;netstandard2.0</TargetFrameworks> - <Version>4.5.4</Version> + <Version>4.5.5</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> + <GeneratePackageOnBuild>true</GeneratePackageOnBuild> </PropertyGroup> <ItemGroup> @@ -25,4 +26,8 @@ <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'"> <PackageReference Include="System.Drawing.Common" Version="4.5.0" /> </ItemGroup> + + <Target Name="PostBuild" AfterTargets="PostBuildEvent"> + <Exec Command="IF NOT "$(ConfigurationName)"=="Release" EXIT /B 0
echo nuget push $(ProjectDir)bin\Release\*.nupkg -ApiKey 123.123a -Source http://nuget.cefcfco.com > NugetPush.bat
echo pause >> NugetPush.bat" /> + </Target> </Project> \ No newline at end of file From c993302450af20b28215f0ccc60dd62583a5c971 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Tue, 17 Nov 2020 15:43:25 +0800 Subject: [PATCH 06/20] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=AC=AC=E4=BA=8C?= =?UTF-8?q?=E5=9D=90=E6=A0=87=E8=BD=B4=E4=B8=BA=E6=8A=98=E7=BA=BF=E5=9B=BE?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E4=B8=8D=E5=B1=95=E7=A4=BA=E7=BA=BF=E6=9D=A1?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ChartUpdater.cs | 14 ++++++++++++++ .../MarkupSimplifierApp/MarkupSimplifierApp.csproj | 4 +--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/OpenXmlPowerTools/ChartUpdater.cs b/OpenXmlPowerTools/ChartUpdater.cs index 61003cb7..c2f900be 100644 --- a/OpenXmlPowerTools/ChartUpdater.cs +++ b/OpenXmlPowerTools/ChartUpdater.cs @@ -138,6 +138,20 @@ private static void MoveSecondChartSeries(ChartPart chartPart, ChartData chartDa var firstSeries = chart.Descendants(C.ser).FirstOrDefault(); firstSeries.Parent.Elements(C.ser).Skip(1).Remove(); + // 如果第二坐标轴为折线图,那么让它正确显示 + if (chartData.SecondChartType == C.lineChart) + { + series.ForEach(x => + { + var spPrs = x.Descendants(C.spPr); + spPrs.Remove(); + + var smooth = new XElement(C.smooth); + smooth.SetAttributeValue(C.val, "0"); + x.Add(smooth); + }); + } + firstSeries.ReplaceWith(series); // 删除旧series diff --git a/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj b/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj index 90ae7ebe..ff153d40 100644 --- a/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj +++ b/OpenXmlPowerToolsExamples/MarkupSimplifierApp/MarkupSimplifierApp.csproj @@ -15,9 +15,7 @@ </ItemGroup> <ItemGroup> - <Compile Update="Form1.cs"> - <SubType>Form</SubType> - </Compile> + <Compile Update="Form1.cs" /> <Compile Update="Form1.Designer.cs"> <SubType>Form</SubType> </Compile> From f5b3ede3e3b7f26e0c70ea77b83f32f8b3932eee Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Tue, 17 Nov 2020 15:52:45 +0800 Subject: [PATCH 07/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BD=93=E6=AC=A1?= =?UTF-8?q?=E7=BA=A7=E5=9D=90=E6=A0=87=E8=BD=B4=E4=B8=BA=E6=8A=98=E7=BA=BF?= =?UTF-8?q?=E5=9B=BE=E6=97=B6=EF=BC=8C=E7=BA=BF=E6=9D=A1=E4=B8=8D=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index 60b12d05..38d8e9a8 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net45;net46;netstandard2.0</TargetFrameworks> - <Version>4.5.5</Version> + <Version>4.5.6</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> From f219e4c2ceaef36c37c467d019babe22094f6c53 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Mon, 16 Aug 2021 17:10:57 +0800 Subject: [PATCH 08/20] remove build script for local nuget server --- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index 38d8e9a8..95ac31b4 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -26,8 +26,4 @@ <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'"> <PackageReference Include="System.Drawing.Common" Version="4.5.0" /> </ItemGroup> - - <Target Name="PostBuild" AfterTargets="PostBuildEvent"> - <Exec Command="IF NOT "$(ConfigurationName)"=="Release" EXIT /B 0
echo nuget push $(ProjectDir)bin\Release\*.nupkg -ApiKey 123.123a -Source http://nuget.cefcfco.com > NugetPush.bat
echo pause >> NugetPush.bat" /> - </Target> </Project> \ No newline at end of file From 1594363bf12d744d7e7de25b0bb790a977effb5a Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Wed, 19 Apr 2023 16:16:33 +0800 Subject: [PATCH 09/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=AC=A1=E8=BD=B4?= =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E5=B1=95=E7=A4=BA=E4=B8=8D=E4=BA=89=E5=8F=96?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ChartUpdater.cs | 99 +++++++++------------- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 2 files changed, 43 insertions(+), 58 deletions(-) diff --git a/OpenXmlPowerTools/ChartUpdater.cs b/OpenXmlPowerTools/ChartUpdater.cs index c2f900be..dbcdad42 100644 --- a/OpenXmlPowerTools/ChartUpdater.cs +++ b/OpenXmlPowerTools/ChartUpdater.cs @@ -63,7 +63,7 @@ public class ChartData /// 组合图表中,第二个图表的序列索引. /// 这些序列数据会被复制到第二个图表的序列中. /// </summary> - public int[] SecondChartSeriesIndex; + public Dictionary<string, string> SecondChartSeriesNames { get; set; } = new Dictionary<string, string>(); public XName SecondChartType; } @@ -102,61 +102,14 @@ public static void UpdateChart(ChartPart chartPart, ChartData chartData) throw new ArgumentException("Invalid chart data"); } - UpdateSeries(chartPart, chartData); - MoveSecondChartSeries(chartPart, chartData); - } - - /// <summary> - /// 移动第二图表的序列数据. - /// </summary> - /// <param name="chartPart">图表部件.</param> - /// <param name="chartData">图表数据.</param> - private static void MoveSecondChartSeries(ChartPart chartPart, ChartData chartData) - { - if (chartData.SecondChartType == null) - { - return; - } - - if (chartData.SecondChartSeriesIndex != null && chartData.SecondChartSeriesIndex.Length == 0) - { - return; - } - - XDocument cpXDoc = chartPart.GetXDocument(); - XElement root = cpXDoc.Root; - - // 根据配置得到序列 - var series = chartData.SecondChartSeriesIndex.Select(x => - root.Descendants(C.ser).ElementAt(x) - ).ToList(); - - var firstParent = series.First().Parent; - - var chart = root.Descendants(chartData.SecondChartType).FirstOrDefault(); - - var firstSeries = chart.Descendants(C.ser).FirstOrDefault(); - firstSeries.Parent.Elements(C.ser).Skip(1).Remove(); + UpdateEmbeddedWorkbook(chartPart, chartData); - // 如果第二坐标轴为折线图,那么让它正确显示 - if (chartData.SecondChartType == C.lineChart) + UpdateSeries(chartPart, chartData); + //如果设置了次轴,更新次轴 + if (chartData.SecondChartSeriesNames.Count > 0) { - series.ForEach(x => - { - var spPrs = x.Descendants(C.spPr); - spPrs.Remove(); - - var smooth = new XElement(C.smooth); - smooth.SetAttributeValue(C.val, "0"); - x.Add(smooth); - }); + UpdateSeries(chartPart, chartData, true); } - - firstSeries.ReplaceWith(series); - - // 删除旧series - series.Remove(); - chartPart.PutXDocument(); } private static Dictionary<int, string> FormatCodes = new Dictionary<int, string>() @@ -191,13 +144,38 @@ private static void MoveSecondChartSeries(ChartPart chartPart, ChartData chartDa { 49, "@" }, }; - private static void UpdateSeries(ChartPart chartPart, ChartData chartData) + /// <summary> + /// + /// </summary> + /// <param name="chartPart"></param> + /// <param name="chartData"></param> + /// <param name="setSecond">设置次级坐标,默认为false</param> + /// <exception cref="OpenXmlPowerToolsException"></exception> + private static void UpdateSeries(ChartPart chartPart, ChartData chartData, bool setSecond = false) { - UpdateEmbeddedWorkbook(chartPart, chartData); - + // update series XDocument cpXDoc = chartPart.GetXDocument(); XElement root = cpXDoc.Root; - var firstSeries = root.Descendants(C.ser).FirstOrDefault(); + + // 序列名 + var seriesNames = chartData.SeriesNames.Except(chartData.SecondChartSeriesNames.Keys); + if (setSecond) + { + seriesNames = chartData.SecondChartSeriesNames.Keys; + } + + var series = root.Descendants(C.ser).ToList(); + // 如果不处理次轴 + if (!setSecond) + { + series = series.Where(x => x.Descendants(C.tx).SelectMany(tx => tx.Descendants(C.v)).Any(v => !chartData.SecondChartSeriesNames.Values.Contains(v.Value))).ToList(); + } + else // 处理次轴 + { + series = series.Where(x => x.Descendants(C.tx).SelectMany(tx => tx.Descendants(C.v)).Any(v => chartData.SecondChartSeriesNames.Values.Contains(v.Value))).ToList(); + } + + var firstSeries = series.FirstOrDefault(); var numRef = firstSeries.Elements(C.val).Elements(C.numRef).FirstOrDefault(); string sheetName = null; var f = (string)firstSeries.Descendants(C.f).FirstOrDefault(); @@ -213,6 +191,9 @@ private static void UpdateSeries(ChartPart chartPart, ChartData chartData) { XElement cat = null; + if (!seriesNames.Contains(sn)) + return null; + var oldCat = firstSeries.Elements(C.cat).FirstOrDefault(); if (oldCat == null) throw new OpenXmlPowerToolsException("Invalid chart markup"); @@ -441,6 +422,10 @@ private static void UpdateSeries(ChartPart chartPart, ChartData chartData) newSer = (XElement)UpdateAccentTransform(newSer, accentNumber); return newSer; }); + + // 删除newSetOfSeries中null的项目 + newSetOfSeries = newSetOfSeries.Where(x => x != null).ToList(); + firstSeries.ReplaceWith(newSetOfSeries); chartPart.PutXDocument(); } diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index 95ac31b4..634d6e6e 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFrameworks>net45;net46;netstandard2.0</TargetFrameworks> + <TargetFrameworks>netstandard2.0</TargetFrameworks> <Version>4.5.6</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> From efa7bfb7b9099b460791c237da79c90f62e0e409 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Wed, 19 Apr 2023 16:48:36 +0800 Subject: [PATCH 10/20] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 4 + OpenXmlPowerTools.sln | 246 +----------------- OpenXmlPowerTools/GlobalSuppressions.cs | 18 ++ OpenXmlPowerTools/NugetPush.bat | 4 +- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- .../DocumentBuilder01.csproj | 3 + 6 files changed, 31 insertions(+), 246 deletions(-) create mode 100644 .editorconfig create mode 100644 OpenXmlPowerTools/GlobalSuppressions.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..cd7c902d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# SA1626: Single-line comments should not use documentation style slashes +dotnet_diagnostic.SA1626.severity = suggestion diff --git a/OpenXmlPowerTools.sln b/OpenXmlPowerTools.sln index 806dc01e..f076c94a 100644 --- a/OpenXmlPowerTools.sln +++ b/OpenXmlPowerTools.sln @@ -1,82 +1,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2036 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33530.505 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenXmlPowerTools", "OpenXmlPowerTools\OpenXmlPowerTools.csproj", "{6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChartUpdater01", "OpenXmlPowerToolsExamples\ChartUpdater01\ChartUpdater01.csproj", "{1B03D24F-FB08-42E1-BB25-2D1BB907991B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder01", "OpenXmlPowerToolsExamples\DocumentBuilder01\DocumentBuilder01.csproj", "{A8A6FCF0-CA4F-4637-8E66-D86603B92204}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder02", "OpenXmlPowerToolsExamples\DocumentBuilder02\DocumentBuilder02.csproj", "{BF8153AA-C390-4D00-98F2-083DEFEC7094}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder03", "OpenXmlPowerToolsExamples\DocumentBuilder03\DocumentBuilder03.csproj", "{BE635672-D3FD-42C5-96E3-EDE50E05CE29}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentBuilder04", "OpenXmlPowerToolsExamples\DocumentBuilder04\DocumentBuilder04.csproj", "{CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FieldRetriever01", "OpenXmlPowerToolsExamples\FieldRetriever01\FieldRetriever01.csproj", "{E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FormattingAssembler01", "OpenXmlPowerToolsExamples\FormattingAssembler01\FormattingAssembler01.csproj", "{6EAF15B6-98BE-428B-A018-A5266521551E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Formulas01", "OpenXmlPowerToolsExamples\Formulas01\Formulas01.csproj", "{618B95DB-3A70-4DC8-BD87-00F636F72453}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlConverter01", "OpenXmlPowerToolsExamples\HtmlConverter01\HtmlConverter01.csproj", "{BC9E7408-508D-482D-8602-96E76ACBB5EA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ListItemRetriever01", "OpenXmlPowerToolsExamples\ListItemRetriever01\ListItemRetriever01.csproj", "{04935FA6-E48B-496F-8D6A-41A59232303D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MarkupSimplifierApp", "OpenXmlPowerToolsExamples\MarkupSimplifierApp\MarkupSimplifierApp.csproj", "{0CCE83BA-8B8B-4B98-8846-B62A61FDF170}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetricsGetter01", "OpenXmlPowerToolsExamples\MetricsGetter01\MetricsGetter01.csproj", "{ED37372C-DFBF-4720-BD4B-CE1415961038}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenXmlRegex01", "OpenXmlPowerToolsExamples\OpenXmlRegex01\OpenXmlRegex01.csproj", "{4330D46F-6703-4BA2-844D-177F722C0820}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PivotTables01", "OpenXmlPowerToolsExamples\PivotTables01\PivotTables01.csproj", "{6785A554-BBBB-480C-8E4D-9FE90DD91A46}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PresentationBuilder01", "OpenXmlPowerToolsExamples\PresentationBuilder01\PresentationBuilder01.csproj", "{A4128935-B707-4D56-B924-27910EC92664}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PresentationBuilder02", "OpenXmlPowerToolsExamples\PresentationBuilder02\PresentationBuilder02.csproj", "{495060B4-BD80-4B18-AC44-4680F0D6D5DB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReferenceAdder01", "OpenXmlPowerToolsExamples\ReferenceAdder01\ReferenceAdder01.csproj", "{211F05D3-F8EE-497F-9DE9-AFFA0A72140D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevisionAccepter01", "OpenXmlPowerToolsExamples\RevisionAccepter01\RevisionAccepter01.csproj", "{84823BA5-B860-4CAF-885E-981D7F121830}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextReplacer01", "OpenXmlPowerToolsExamples\TextReplacer01\TextReplacer01.csproj", "{5CA29B44-C4A5-4310-9429-553F0BC9FC1D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextReplacer02", "OpenXmlPowerToolsExamples\TextReplacer02\TextReplacer02.csproj", "{153E5218-E9C0-4ED8-9073-0802204C8B90}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler01", "OpenXmlPowerToolsExamples\DocumentAssembler01\DocumentAssembler01.csproj", "{EFE77658-EDD7-4597-8016-CBE4A18951B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler", "OpenXmlPowerToolsExamples\DocumentAssembler\DocumentAssembler.csproj", "{2D081A36-48F9-4A09-8247-420682545492}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpreadsheetWriter01", "OpenXmlPowerToolsExamples\SpreadsheetWriter01\SpreadsheetWriter01.csproj", "{0911F996-DF86-4FB1-A1CE-0539599EC0E0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpreadsheetWriter02", "OpenXmlPowerToolsExamples\SpreadsheetWriter02\SpreadsheetWriter02.csproj", "{DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenXmlPowerTools.Tests", "OpenXmlPowerTools.Tests\OpenXmlPowerTools.Tests.csproj", "{B1328B70-33B8-40E0-A729-38C34D659B5C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler02", "OpenXmlPowerToolsExamples\DocumentAssembler02\DocumentAssembler02.csproj", "{D6DFAC7C-82F4-4318-A9F0-6450D2945D96}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlToWmlConverter01", "OpenXmlPowerToolsExamples\HtmlToWmlConverter01\HtmlToWmlConverter01.csproj", "{9E194D13-F5A0-4430-8F87-D74326457385}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentAssembler03", "OpenXmlPowerToolsExamples\DocumentAssembler03\DocumentAssembler03.csproj", "{214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlToWmlConverter02", "OpenXmlPowerToolsExamples\HtmlToWmlConverter02\HtmlToWmlConverter02.csproj", "{1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlToHtmlConverter01", "OpenXmlPowerToolsExamples\WmlToHtmlConverter01\WmlToHtmlConverter01.csproj", "{396D9209-0D9A-4E61-9471-04C71F6CA6B9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlToHtmlConverter02", "OpenXmlPowerToolsExamples\WmlToHtmlConverter02\WmlToHtmlConverter02.csproj", "{D4078011-2611-46A7-8A30-55E4AB8FA786}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmlDataRetriever01", "OpenXmlPowerToolsExamples\SmlDataRetriever01\SmlDataRetriever01.csproj", "{DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlComparer01", "OpenXmlPowerToolsExamples\WmlComparer01\WmlComparer01.csproj", "{C9CAA69C-575A-442E-9D8A-69C53B39D72C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WmlComparer02", "OpenXmlPowerToolsExamples\WmlComparer02\WmlComparer02.csproj", "{3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{A83D6B58-6D38-46AF-8C20-5CFC170A1063}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9AFB8C96-1E6E-483E-9882-75D2483E7076}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets LICENSE.txt = LICENSE.txt @@ -95,181 +26,10 @@ Global {6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {6F957FF3-AFCC-4D69-8FBC-71AE21BC45C9}.Release|Any CPU.Build.0 = Release|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B03D24F-FB08-42E1-BB25-2D1BB907991B}.Release|Any CPU.Build.0 = Release|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A8A6FCF0-CA4F-4637-8E66-D86603B92204}.Release|Any CPU.Build.0 = Release|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF8153AA-C390-4D00-98F2-083DEFEC7094}.Release|Any CPU.Build.0 = Release|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE635672-D3FD-42C5-96E3-EDE50E05CE29}.Release|Any CPU.Build.0 = Release|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB}.Release|Any CPU.Build.0 = Release|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02}.Release|Any CPU.Build.0 = Release|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6EAF15B6-98BE-428B-A018-A5266521551E}.Release|Any CPU.Build.0 = Release|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Debug|Any CPU.Build.0 = Debug|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Release|Any CPU.ActiveCfg = Release|Any CPU - {618B95DB-3A70-4DC8-BD87-00F636F72453}.Release|Any CPU.Build.0 = Release|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BC9E7408-508D-482D-8602-96E76ACBB5EA}.Release|Any CPU.Build.0 = Release|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {04935FA6-E48B-496F-8D6A-41A59232303D}.Release|Any CPU.Build.0 = Release|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170}.Release|Any CPU.Build.0 = Release|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED37372C-DFBF-4720-BD4B-CE1415961038}.Release|Any CPU.Build.0 = Release|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4330D46F-6703-4BA2-844D-177F722C0820}.Release|Any CPU.Build.0 = Release|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6785A554-BBBB-480C-8E4D-9FE90DD91A46}.Release|Any CPU.Build.0 = Release|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4128935-B707-4D56-B924-27910EC92664}.Release|Any CPU.Build.0 = Release|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {495060B4-BD80-4B18-AC44-4680F0D6D5DB}.Release|Any CPU.Build.0 = Release|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D}.Release|Any CPU.Build.0 = Release|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Debug|Any CPU.Build.0 = Debug|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Release|Any CPU.ActiveCfg = Release|Any CPU - {84823BA5-B860-4CAF-885E-981D7F121830}.Release|Any CPU.Build.0 = Release|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D}.Release|Any CPU.Build.0 = Release|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Debug|Any CPU.Build.0 = Debug|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Release|Any CPU.ActiveCfg = Release|Any CPU - {153E5218-E9C0-4ED8-9073-0802204C8B90}.Release|Any CPU.Build.0 = Release|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EFE77658-EDD7-4597-8016-CBE4A18951B0}.Release|Any CPU.Build.0 = Release|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2D081A36-48F9-4A09-8247-420682545492}.Release|Any CPU.Build.0 = Release|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0911F996-DF86-4FB1-A1CE-0539599EC0E0}.Release|Any CPU.Build.0 = Release|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02}.Release|Any CPU.Build.0 = Release|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B1328B70-33B8-40E0-A729-38C34D659B5C}.Release|Any CPU.Build.0 = Release|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96}.Release|Any CPU.Build.0 = Release|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E194D13-F5A0-4430-8F87-D74326457385}.Release|Any CPU.Build.0 = Release|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0}.Release|Any CPU.Build.0 = Release|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4}.Release|Any CPU.Build.0 = Release|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {396D9209-0D9A-4E61-9471-04C71F6CA6B9}.Release|Any CPU.Build.0 = Release|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D4078011-2611-46A7-8A30-55E4AB8FA786}.Release|Any CPU.Build.0 = Release|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D}.Release|Any CPU.Build.0 = Release|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C9CAA69C-575A-442E-9D8A-69C53B39D72C}.Release|Any CPU.Build.0 = Release|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {1B03D24F-FB08-42E1-BB25-2D1BB907991B} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {A8A6FCF0-CA4F-4637-8E66-D86603B92204} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {BF8153AA-C390-4D00-98F2-083DEFEC7094} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {BE635672-D3FD-42C5-96E3-EDE50E05CE29} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {CE0ECABB-03AD-42CE-A5BD-D0CC4DCE35AB} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {E1FD7B15-FA09-4F7F-A30E-9FBD9F765D02} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {6EAF15B6-98BE-428B-A018-A5266521551E} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {618B95DB-3A70-4DC8-BD87-00F636F72453} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {BC9E7408-508D-482D-8602-96E76ACBB5EA} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {04935FA6-E48B-496F-8D6A-41A59232303D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {0CCE83BA-8B8B-4B98-8846-B62A61FDF170} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {ED37372C-DFBF-4720-BD4B-CE1415961038} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {4330D46F-6703-4BA2-844D-177F722C0820} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {6785A554-BBBB-480C-8E4D-9FE90DD91A46} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {A4128935-B707-4D56-B924-27910EC92664} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {495060B4-BD80-4B18-AC44-4680F0D6D5DB} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {211F05D3-F8EE-497F-9DE9-AFFA0A72140D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {84823BA5-B860-4CAF-885E-981D7F121830} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {5CA29B44-C4A5-4310-9429-553F0BC9FC1D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {153E5218-E9C0-4ED8-9073-0802204C8B90} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {EFE77658-EDD7-4597-8016-CBE4A18951B0} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {2D081A36-48F9-4A09-8247-420682545492} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {0911F996-DF86-4FB1-A1CE-0539599EC0E0} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {DF1D84AF-27B8-4F87-A673-CCFADC3AAF02} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {D6DFAC7C-82F4-4318-A9F0-6450D2945D96} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {9E194D13-F5A0-4430-8F87-D74326457385} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {214F0E80-D2E3-4E19-A3FC-2BE15B3906B0} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {1E75CB7D-2A4A-4B03-80A9-7B7D59B18BB4} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {396D9209-0D9A-4E61-9471-04C71F6CA6B9} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {D4078011-2611-46A7-8A30-55E4AB8FA786} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {DCE8EC51-1E58-49A0-82CF-5BE269FA0A9D} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {C9CAA69C-575A-442E-9D8A-69C53B39D72C} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - {3D1C46E1-7A9E-4A4B-8D95-68613603DEDF} = {A83D6B58-6D38-46AF-8C20-5CFC170A1063} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E623EFF5-2CA4-4FA0-B3AB-53F921DA212E} EndGlobalSection diff --git a/OpenXmlPowerTools/GlobalSuppressions.cs b/OpenXmlPowerTools/GlobalSuppressions.cs new file mode 100644 index 00000000..1537b2bd --- /dev/null +++ b/OpenXmlPowerTools/GlobalSuppressions.cs @@ -0,0 +1,18 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; +[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1004:Documentation lines should begin with single space", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1612:Element parameter documentation should match element parameters", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1616:Element return value documentation should have text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1617:Void return value should not be documented", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1614:Element parameter documentation should have text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1627:Documentation text should not be empty", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1606:Element documentation should have summary text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1629:Documentation text should end with a period", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1514:Element documentation header should be preceded by blank line", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1626:Single-line comments should not use documentation style slashes", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1636:File header copyright text should match", Justification = "<挂起>")] diff --git a/OpenXmlPowerTools/NugetPush.bat b/OpenXmlPowerTools/NugetPush.bat index b9cf2dc8..2beb6680 100644 --- a/OpenXmlPowerTools/NugetPush.bat +++ b/OpenXmlPowerTools/NugetPush.bat @@ -1,2 +1,2 @@ -nuget push C:\Work\github\Open-Xml-PowerTools\OpenXmlPowerTools\bin\Release\*.nupkg -ApiKey 123.123a -Source http://nuget.cefcfco.com -pause +dotnet nuget push .\bin\Release\*.nupkg -k 123.123a -s http://nuget.cefcfco.com +pause \ No newline at end of file diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index 634d6e6e..0b15c24f 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.6</Version> + <Version>4.5.7</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> diff --git a/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj b/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj index e188d465..5f593cb0 100644 --- a/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj +++ b/OpenXmlPowerToolsExamples/DocumentBuilder01/DocumentBuilder01.csproj @@ -3,6 +3,9 @@ <OutputType>Exe</OutputType> <TargetFrameworks>net45;net46;netcoreapp2.0</TargetFrameworks> </PropertyGroup> + <ItemGroup> + <None Include="..\..\.editorconfig" Link=".editorconfig" /> + </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\OpenXmlPowerTools\OpenXmlPowerTools.csproj" /> From 3216baa24a008b7a7a6d5d4eaa5f2b8134682f01 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Wed, 19 Apr 2023 16:50:07 +0800 Subject: [PATCH 11/20] =?UTF-8?q?nuget=E5=8C=85=E7=89=88=E6=9C=AC=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index 0b15c24f..a4d382b0 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,11 +1,12 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.7</Version> + <Version>4.5.8</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> + <IsPublishable>True</IsPublishable> </PropertyGroup> <ItemGroup> From 31b752456f35f27190ebedecbbcc2c7fc908582a Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Wed, 19 Apr 2023 17:42:02 +0800 Subject: [PATCH 12/20] =?UTF-8?q?=E5=A6=82=E6=9E=9C=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E6=89=BE=E5=88=B0=E6=AC=A1=E8=BD=B4=E5=BA=8F=E5=88=97=E5=88=99?= =?UTF-8?q?=E6=8A=9B=E5=87=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ChartUpdater.cs | 12 ++++++++---- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/OpenXmlPowerTools/ChartUpdater.cs b/OpenXmlPowerTools/ChartUpdater.cs index dbcdad42..908c3fab 100644 --- a/OpenXmlPowerTools/ChartUpdater.cs +++ b/OpenXmlPowerTools/ChartUpdater.cs @@ -60,12 +60,10 @@ public class ChartData public double[][] Values; /// <summary> - /// 组合图表中,第二个图表的序列索引. - /// 这些序列数据会被复制到第二个图表的序列中. + /// 组合图表中,次轴图表的序列名称映射 + /// 映射规则为:chatData中的序列名对应模板中的序列名。 /// </summary> public Dictionary<string, string> SecondChartSeriesNames { get; set; } = new Dictionary<string, string>(); - - public XName SecondChartType; } public class ChartUpdater @@ -169,10 +167,16 @@ private static void UpdateSeries(ChartPart chartPart, ChartData chartData, bool if (!setSecond) { series = series.Where(x => x.Descendants(C.tx).SelectMany(tx => tx.Descendants(C.v)).Any(v => !chartData.SecondChartSeriesNames.Values.Contains(v.Value))).ToList(); + + if (series == null || series.Count == 0) + throw new OpenXmlPowerToolsException("未找到图表主序列"); } else // 处理次轴 { series = series.Where(x => x.Descendants(C.tx).SelectMany(tx => tx.Descendants(C.v)).Any(v => chartData.SecondChartSeriesNames.Values.Contains(v.Value))).ToList(); + + if (series == null || series.Count == 0) + throw new OpenXmlPowerToolsException("未找到次轴序列,请检查次轴映射字典"); } var firstSeries = series.FirstOrDefault(); diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index a4d382b0..d54cbe19 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.8</Version> + <Version>4.5.9</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> From 5b4cf0177ec1d5ee7fa7d4392f72389d41bbbfd5 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Mon, 24 Apr 2023 14:50:26 +0800 Subject: [PATCH 13/20] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ImageReplacer.cs | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 OpenXmlPowerTools/ImageReplacer.cs diff --git a/OpenXmlPowerTools/ImageReplacer.cs b/OpenXmlPowerTools/ImageReplacer.cs new file mode 100644 index 00000000..c7640b4c --- /dev/null +++ b/OpenXmlPowerTools/ImageReplacer.cs @@ -0,0 +1,43 @@ +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Wordprocessing; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace OpenXmlPowerTools +{ + public class ImageReplacer + { + public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, string newImagePath) + { + var mainDocumentPart = wDoc.MainDocumentPart; + var mdXDoc = mainDocumentPart.GetXDocument(); + var cc = mdXDoc.Descendants(W.sdt) + .FirstOrDefault(sdt => (string)sdt.Elements(W.sdtPr).Elements(W.tag).Attributes(W.val).FirstOrDefault() == contentControlTag); + + if (cc != null) + { + var imageId = (string)cc.Descendants(A.blip).Attributes(R.embed).FirstOrDefault(); + + if (imageId != null) + { + ImagePart imagePart = (ImagePart)mainDocumentPart.GetPartById(imageId); + ReplaceNewImage(imagePart, newImagePath); + } + } + + return false; + } + + private static void ReplaceNewImage(ImagePart imagePart, string newImagePath) + { + byte[] imageBytes = File.ReadAllBytes(newImagePath); + BinaryWriter writer = new BinaryWriter(imagePart.GetStream()); + writer.Write(imageBytes); + writer.Close(); + } + } +} From 9bbb7594e5cc008bf951905749cb05c2f31a56bf Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Mon, 24 Apr 2023 15:02:04 +0800 Subject: [PATCH 14/20] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=99=A8,=E5=A2=9E=E5=8A=A0byte[]=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E8=BE=93=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ImageReplacer.cs | 67 ++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/OpenXmlPowerTools/ImageReplacer.cs b/OpenXmlPowerTools/ImageReplacer.cs index c7640b4c..1ce3ba85 100644 --- a/OpenXmlPowerTools/ImageReplacer.cs +++ b/OpenXmlPowerTools/ImageReplacer.cs @@ -9,9 +9,64 @@ namespace OpenXmlPowerTools { + /// <summary> + /// 图片替换器 + /// </summary> public class ImageReplacer { + public byte[] ImageBytes { get; private set; } + + /// <summary> + /// 图片替换器构造函数 + /// </summary> + /// <param name="imageBytes">新图片的字节数组</param> + public ImageReplacer(byte[] imageBytes) + { + ImageBytes = imageBytes; + } + + /// <summary> + /// 新图片路径 + /// </summary> + /// <param name="newImagePath"></param> + public ImageReplacer(string newImagePath) + { + ImageBytes = File.ReadAllBytes(newImagePath); + } + + /// <summary> + /// 替换图片 + /// </summary> + /// <param name="wDoc">Word文档对象</param> + /// <param name="contentControlTag">要替换的控件tag</param> + /// <param name="newImagePath">新图片的路径</param> + /// <returns></returns> public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, string newImagePath) + { + var replacer = new ImageReplacer(newImagePath); + return replacer.Replace(wDoc, contentControlTag); + } + + /// <summary> + /// 替换图片 + /// </summary> + /// <param name="wDoc">Word文档对象</param> + /// <param name="contentControlTag">要替换的控件tag</param> + /// <param name="imageBytes">新图片的路径</param> + /// <returns></returns> + public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, byte[] imageBytes) + { + var replacer = new ImageReplacer(imageBytes); + return replacer.Replace(wDoc, contentControlTag); + } + + /// <summary> + /// 替换图片 + /// </summary> + /// <param name="wDoc"></param> + /// <param name="contentControlTag"></param> + /// <returns></returns> + private bool Replace(WordprocessingDocument wDoc, string contentControlTag) { var mainDocumentPart = wDoc.MainDocumentPart; var mdXDoc = mainDocumentPart.GetXDocument(); @@ -25,19 +80,25 @@ public static bool ReplaceImage(WordprocessingDocument wDoc, string contentContr if (imageId != null) { ImagePart imagePart = (ImagePart)mainDocumentPart.GetPartById(imageId); - ReplaceNewImage(imagePart, newImagePath); + ReplaceNewImage(imagePart, this.ImageBytes); + return true; } } return false; } - private static void ReplaceNewImage(ImagePart imagePart, string newImagePath) + private void ReplaceNewImage(ImagePart imagePart, byte[] imageBytes) { - byte[] imageBytes = File.ReadAllBytes(newImagePath); BinaryWriter writer = new BinaryWriter(imagePart.GetStream()); writer.Write(imageBytes); writer.Close(); } + + private void ReplaceNewImage(ImagePart imagePart, string newImagePath) + { + byte[] imageBytes = File.ReadAllBytes(newImagePath); + ReplaceNewImage(imagePart, imageBytes); + } } } From a7822a4695b3b6a51e8e9b8776ad7df139bd1014 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Mon, 24 Apr 2023 15:08:05 +0800 Subject: [PATCH 15/20] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/GlobalSuppressions.cs | 2 ++ OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenXmlPowerTools/GlobalSuppressions.cs b/OpenXmlPowerTools/GlobalSuppressions.cs index 1537b2bd..64410479 100644 --- a/OpenXmlPowerTools/GlobalSuppressions.cs +++ b/OpenXmlPowerTools/GlobalSuppressions.cs @@ -16,3 +16,5 @@ [assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1514:Element documentation header should be preceded by blank line", Justification = "<挂起>")] [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1626:Single-line comments should not use documentation style slashes", Justification = "<挂起>")] [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1636:File header copyright text should match", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1642:Constructor summary documentation should begin with standard text", Justification = "<挂起>")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File should have header", Justification = "<挂起>")] diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index d54cbe19..e010612e 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.9</Version> + <Version>4.5.10-preview</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> From 1dfc59f84f11daadbb0e908bcb06cd46566ae7dd Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Tue, 25 Apr 2023 14:36:44 +0800 Subject: [PATCH 16/20] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E6=97=B6=E5=80=99=EF=BC=8C=E5=B0=86=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E5=9B=BE=E7=89=87=E5=85=A8=E9=83=A8=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ImageReplacer.cs | 21 +++++++++++++++------ OpenXmlPowerTools/NugetPush.bat | 2 ++ OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/OpenXmlPowerTools/ImageReplacer.cs b/OpenXmlPowerTools/ImageReplacer.cs index 1ce3ba85..e8923eb4 100644 --- a/OpenXmlPowerTools/ImageReplacer.cs +++ b/OpenXmlPowerTools/ImageReplacer.cs @@ -12,7 +12,7 @@ namespace OpenXmlPowerTools /// <summary> /// 图片替换器 /// </summary> - public class ImageReplacer + public class ImageUpdater { public byte[] ImageBytes { get; private set; } @@ -20,7 +20,7 @@ public class ImageReplacer /// 图片替换器构造函数 /// </summary> /// <param name="imageBytes">新图片的字节数组</param> - public ImageReplacer(byte[] imageBytes) + public ImageUpdater(byte[] imageBytes) { ImageBytes = imageBytes; } @@ -29,7 +29,7 @@ public ImageReplacer(byte[] imageBytes) /// 新图片路径 /// </summary> /// <param name="newImagePath"></param> - public ImageReplacer(string newImagePath) + public ImageUpdater(string newImagePath) { ImageBytes = File.ReadAllBytes(newImagePath); } @@ -43,7 +43,7 @@ public ImageReplacer(string newImagePath) /// <returns></returns> public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, string newImagePath) { - var replacer = new ImageReplacer(newImagePath); + var replacer = new ImageUpdater(newImagePath); return replacer.Replace(wDoc, contentControlTag); } @@ -56,7 +56,7 @@ public static bool ReplaceImage(WordprocessingDocument wDoc, string contentContr /// <returns></returns> public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, byte[] imageBytes) { - var replacer = new ImageReplacer(imageBytes); + var replacer = new ImageUpdater(imageBytes); return replacer.Replace(wDoc, contentControlTag); } @@ -81,6 +81,7 @@ private bool Replace(WordprocessingDocument wDoc, string contentControlTag) { ImagePart imagePart = (ImagePart)mainDocumentPart.GetPartById(imageId); ReplaceNewImage(imagePart, this.ImageBytes); + mainDocumentPart.PutXDocument(); return true; } } @@ -90,7 +91,15 @@ private bool Replace(WordprocessingDocument wDoc, string contentControlTag) private void ReplaceNewImage(ImagePart imagePart, byte[] imageBytes) { - BinaryWriter writer = new BinaryWriter(imagePart.GetStream()); + var stream = imagePart.GetStream(); + + // stream保存为图片文件 + //using (var fileStream = new FileStream("f:\\test1.jpg", FileMode.Create)) + //{ + // stream.CopyTo(fileStream); + //} + + BinaryWriter writer = new BinaryWriter(stream); writer.Write(imageBytes); writer.Close(); } diff --git a/OpenXmlPowerTools/NugetPush.bat b/OpenXmlPowerTools/NugetPush.bat index 2beb6680..33e81789 100644 --- a/OpenXmlPowerTools/NugetPush.bat +++ b/OpenXmlPowerTools/NugetPush.bat @@ -1,2 +1,4 @@ +del .\bin\Release\*.nupkg +dotnet pack -o ./bin/release dotnet nuget push .\bin\Release\*.nupkg -k 123.123a -s http://nuget.cefcfco.com pause \ No newline at end of file diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index e010612e..55137278 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.10-preview</Version> + <Version>4.5.10.1-preview</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> From e7926ce58a6b14e6216d05afd89d18c6ab96be73 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Wed, 17 May 2023 14:27:16 +0800 Subject: [PATCH 17/20] =?UTF-8?q?=E5=9B=BE=E7=89=87=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E5=90=8E=EF=BC=8C=E5=8E=BB=E6=8E=89=E5=8C=85=E5=9B=B4=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=9A=84=E8=87=AA=E5=AE=9A=E4=B9=89=E6=8E=A7=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ImageReplacer.cs | 19 +++++++++++-------- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/OpenXmlPowerTools/ImageReplacer.cs b/OpenXmlPowerTools/ImageReplacer.cs index e8923eb4..8f6dcf57 100644 --- a/OpenXmlPowerTools/ImageReplacer.cs +++ b/OpenXmlPowerTools/ImageReplacer.cs @@ -75,15 +75,24 @@ private bool Replace(WordprocessingDocument wDoc, string contentControlTag) if (cc != null) { + // 替换imagePart var imageId = (string)cc.Descendants(A.blip).Attributes(R.embed).FirstOrDefault(); if (imageId != null) { ImagePart imagePart = (ImagePart)mainDocumentPart.GetPartById(imageId); ReplaceNewImage(imagePart, this.ImageBytes); - mainDocumentPart.PutXDocument(); - return true; } + + // 替换cc + var paragraph = cc.Descendants(W.sdtContent).Descendants(W.p).FirstOrDefault(); + if (paragraph != null) + { + cc.ReplaceWith(paragraph); + } + + mainDocumentPart.PutXDocument(); + return true; } return false; @@ -93,12 +102,6 @@ private void ReplaceNewImage(ImagePart imagePart, byte[] imageBytes) { var stream = imagePart.GetStream(); - // stream保存为图片文件 - //using (var fileStream = new FileStream("f:\\test1.jpg", FileMode.Create)) - //{ - // stream.CopyTo(fileStream); - //} - BinaryWriter writer = new BinaryWriter(stream); writer.Write(imageBytes); writer.Close(); diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index 55137278..38afb8d2 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.10.1-preview</Version> + <Version>4.5.10.2</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> From 7fab0b1a795fe758f0f611b263fa5d6a84488be3 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Wed, 17 May 2023 17:21:29 +0800 Subject: [PATCH 18/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E6=9B=B4=E6=96=B0=E5=AE=BD=E5=BA=A6?= =?UTF-8?q?=E5=92=8C=E9=AB=98=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/Helpers/ImageHelper.cs | 49 +++++++++ OpenXmlPowerTools/ImageReplacer.cs | 110 ++++++++++++++++++--- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 3 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 OpenXmlPowerTools/Helpers/ImageHelper.cs diff --git a/OpenXmlPowerTools/Helpers/ImageHelper.cs b/OpenXmlPowerTools/Helpers/ImageHelper.cs new file mode 100644 index 00000000..822f28d9 --- /dev/null +++ b/OpenXmlPowerTools/Helpers/ImageHelper.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace OpenXmlPowerTools.Helpers +{ + public class ImageHelper + { + public static (int width, int height) GetImageMetrics(Stream imageData, ImageFormat imageFormat) + { + var width = 0; + var height = 0; + + if (imageFormat == ImageFormat.Emf) + { + using (var metafile = new Metafile(imageData)) + { + width = metafile.Width; // 获取宽度 + height = metafile.Height; // 获取高度 + } + } + else + { + using (var image = Image.FromStream(imageData)) + { + width = image.Width; // 获取宽度 + height = image.Height; // 获取高度 + } + } + + return (width, height); + } + + /// <summary> + /// 获取图片的宽和高 + /// </summary> + /// <param name="newImagePath"></param> + /// <returns></returns> + public static (int width, int height) GetImageMetrics(string newImagePath, ImageFormat imageFormat) + { + var ext = Path.GetExtension(newImagePath).ToLower(); + var stream = File.OpenRead(newImagePath); + return GetImageMetrics(stream, imageFormat); + } + } +} diff --git a/OpenXmlPowerTools/ImageReplacer.cs b/OpenXmlPowerTools/ImageReplacer.cs index 8f6dcf57..8b799b4d 100644 --- a/OpenXmlPowerTools/ImageReplacer.cs +++ b/OpenXmlPowerTools/ImageReplacer.cs @@ -1,7 +1,9 @@ using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; +using OpenXmlPowerTools.Helpers; using System; using System.Collections.Generic; +using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; @@ -14,24 +16,34 @@ namespace OpenXmlPowerTools /// </summary> public class ImageUpdater { + private readonly ImageFormat _imageFormat; + private readonly int? _maxWidth; + private readonly int? _maxHeight; + public byte[] ImageBytes { get; private set; } /// <summary> /// 图片替换器构造函数 /// </summary> /// <param name="imageBytes">新图片的字节数组</param> - public ImageUpdater(byte[] imageBytes) + public ImageUpdater(byte[] imageBytes, ImageFormat imageFormat, int? maxWidth, int? maxHeight) { ImageBytes = imageBytes; + _imageFormat = imageFormat; + _maxWidth = maxWidth; + _maxHeight = maxHeight; } /// <summary> /// 新图片路径 /// </summary> /// <param name="newImagePath"></param> - public ImageUpdater(string newImagePath) + public ImageUpdater(string newImagePath, ImageFormat imageFormat, int? maxWidth, int? maxHeight) { ImageBytes = File.ReadAllBytes(newImagePath); + _imageFormat = imageFormat; + _maxWidth = maxWidth; + _maxHeight = maxHeight; } /// <summary> @@ -41,9 +53,14 @@ public ImageUpdater(string newImagePath) /// <param name="contentControlTag">要替换的控件tag</param> /// <param name="newImagePath">新图片的路径</param> /// <returns></returns> - public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, string newImagePath) + public static bool ReplaceImage(WordprocessingDocument wDoc, + string contentControlTag, + string newImagePath, + ImageFormat imageFormat, + int? maxWidth = null, + int? maxHeight = null) { - var replacer = new ImageUpdater(newImagePath); + var replacer = new ImageUpdater(newImagePath, imageFormat, maxWidth, maxHeight); return replacer.Replace(wDoc, contentControlTag); } @@ -54,9 +71,14 @@ public static bool ReplaceImage(WordprocessingDocument wDoc, string contentContr /// <param name="contentControlTag">要替换的控件tag</param> /// <param name="imageBytes">新图片的路径</param> /// <returns></returns> - public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, byte[] imageBytes) + public static bool ReplaceImage(WordprocessingDocument wDoc, + string contentControlTag, + byte[] imageBytes, + ImageFormat imageFormat, + int? maxWidth = null, + int? maxHeight = null) { - var replacer = new ImageUpdater(imageBytes); + var replacer = new ImageUpdater(imageBytes, imageFormat, maxWidth, maxHeight); return replacer.Replace(wDoc, contentControlTag); } @@ -84,6 +106,10 @@ private bool Replace(WordprocessingDocument wDoc, string contentControlTag) ReplaceNewImage(imagePart, this.ImageBytes); } + + // 修改宽度和高度 + UpdateImageMetrics(cc); + // 替换cc var paragraph = cc.Descendants(W.sdtContent).Descendants(W.p).FirstOrDefault(); if (paragraph != null) @@ -98,6 +124,72 @@ private bool Replace(WordprocessingDocument wDoc, string contentControlTag) return false; } + /// <summary> + /// 更新图片宽高 + /// </summary> + /// <param name="cc"></param> + private void UpdateImageMetrics(XElement cc) + { + float dpi = 96; + + var imgStream = new MemoryStream(this.ImageBytes); + var (w, h) = ImageHelper.GetImageMetrics(imgStream, this._imageFormat); + + // 如果设置了最大宽度或最大高度,则按比例缩放 + if (this._maxWidth.HasValue || this._maxHeight.HasValue) + { + var ratio = (float)w / h; + if (this._maxWidth.HasValue && this._maxHeight.HasValue) + { + if (ratio > (float)this._maxWidth.Value / this._maxHeight.Value) + { + w = this._maxWidth.Value; + h = (int)(w / ratio); + } + else + { + h = this._maxHeight.Value; + w = (int)(h * ratio); + } + } + else if (this._maxWidth.HasValue) + { + w = this._maxWidth.Value; + h = (int)(w / ratio); + } + else + { + h = this._maxHeight.Value; + w = (int)(h * ratio); + } + } + + var cx = (long)(w / dpi * 914400); + var cy = (long)(h / dpi * 914400); + + var drawing = cc.Descendants(W.drawing).FirstOrDefault(); + if (drawing != null) + { + var extent = drawing.Descendants(WP.extent).FirstOrDefault(); + if (extent != null) + { + extent.SetAttributeValue("cx", cx); + extent.SetAttributeValue("cy", cy); + } + var aExtent = drawing.Descendants(A.graphic).Descendants(Pic.spPr).Descendants(A.ext).FirstOrDefault(); + if (aExtent != null) + { + aExtent.SetAttributeValue("cx", cx); + aExtent.SetAttributeValue("cy", cy); + } + } + } + + /// <summary> + /// 替换新图片 + /// </summary> + /// <param name="imagePart"></param> + /// <param name="imageBytes"></param> private void ReplaceNewImage(ImagePart imagePart, byte[] imageBytes) { var stream = imagePart.GetStream(); @@ -106,11 +198,5 @@ private void ReplaceNewImage(ImagePart imagePart, byte[] imageBytes) writer.Write(imageBytes); writer.Close(); } - - private void ReplaceNewImage(ImagePart imagePart, string newImagePath) - { - byte[] imageBytes = File.ReadAllBytes(newImagePath); - ReplaceNewImage(imagePart, imageBytes); - } } } diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index 38afb8d2..ca1673d2 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.10.2</Version> + <Version>4.5.10.4</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId> From 30b04c6b2d03e439da19af7c1926da27f7ced0af Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Thu, 18 May 2023 10:12:58 +0800 Subject: [PATCH 19/20] =?UTF-8?q?=E5=9B=BE=E7=89=87=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=8F=AF=E4=BB=A5=E8=AE=BE=E7=BD=AE=E5=AE=BD?= =?UTF-8?q?=E9=AB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/ImageReplacer.cs | 127 +++++++++++++++++++---------- 1 file changed, 85 insertions(+), 42 deletions(-) diff --git a/OpenXmlPowerTools/ImageReplacer.cs b/OpenXmlPowerTools/ImageReplacer.cs index 8b799b4d..579fea53 100644 --- a/OpenXmlPowerTools/ImageReplacer.cs +++ b/OpenXmlPowerTools/ImageReplacer.cs @@ -17,8 +17,16 @@ namespace OpenXmlPowerTools public class ImageUpdater { private readonly ImageFormat _imageFormat; - private readonly int? _maxWidth; - private readonly int? _maxHeight; + + /// <summary> + /// 设置的宽度,可以为百分比,如果不填则默认使用页面宽度 + /// </summary> + private readonly string _width; + + /// <summary> + /// 设置高度,可以为百分比,如果不填则根据宽度缩放后自适应 + /// </summary> + private readonly string _height; public byte[] ImageBytes { get; private set; } @@ -26,24 +34,24 @@ public class ImageUpdater /// 图片替换器构造函数 /// </summary> /// <param name="imageBytes">新图片的字节数组</param> - public ImageUpdater(byte[] imageBytes, ImageFormat imageFormat, int? maxWidth, int? maxHeight) + public ImageUpdater(byte[] imageBytes, ImageFormat imageFormat, string width = null, string height = null) { ImageBytes = imageBytes; _imageFormat = imageFormat; - _maxWidth = maxWidth; - _maxHeight = maxHeight; + _width = width; + _height = height; } /// <summary> /// 新图片路径 /// </summary> /// <param name="newImagePath"></param> - public ImageUpdater(string newImagePath, ImageFormat imageFormat, int? maxWidth, int? maxHeight) + public ImageUpdater(string newImagePath, ImageFormat imageFormat, string width = null, string height = null) { ImageBytes = File.ReadAllBytes(newImagePath); _imageFormat = imageFormat; - _maxWidth = maxWidth; - _maxHeight = maxHeight; + _width = width; + _height = height; } /// <summary> @@ -57,10 +65,10 @@ public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, string newImagePath, ImageFormat imageFormat, - int? maxWidth = null, - int? maxHeight = null) + string width = null, + string height = null) { - var replacer = new ImageUpdater(newImagePath, imageFormat, maxWidth, maxHeight); + var replacer = new ImageUpdater(newImagePath, imageFormat, width, height); return replacer.Replace(wDoc, contentControlTag); } @@ -75,10 +83,10 @@ public static bool ReplaceImage(WordprocessingDocument wDoc, string contentControlTag, byte[] imageBytes, ImageFormat imageFormat, - int? maxWidth = null, - int? maxHeight = null) + string width = null, + string height = null) { - var replacer = new ImageUpdater(imageBytes, imageFormat, maxWidth, maxHeight); + var replacer = new ImageUpdater(imageBytes, imageFormat, width, height); return replacer.Replace(wDoc, contentControlTag); } @@ -106,9 +114,8 @@ private bool Replace(WordprocessingDocument wDoc, string contentControlTag) ReplaceNewImage(imagePart, this.ImageBytes); } - // 修改宽度和高度 - UpdateImageMetrics(cc); + UpdateImageMetrics(mdXDoc, cc); // 替换cc var paragraph = cc.Descendants(W.sdtContent).Descendants(W.p).FirstOrDefault(); @@ -128,44 +135,72 @@ private bool Replace(WordprocessingDocument wDoc, string contentControlTag) /// 更新图片宽高 /// </summary> /// <param name="cc"></param> - private void UpdateImageMetrics(XElement cc) + private void UpdateImageMetrics(XDocument mdXDoc, XElement cc) { float dpi = 96; + // 得到图片宽高 var imgStream = new MemoryStream(this.ImageBytes); - var (w, h) = ImageHelper.GetImageMetrics(imgStream, this._imageFormat); + var (imgWidth, imgHeight) = ImageHelper.GetImageMetrics(imgStream, this._imageFormat); - // 如果设置了最大宽度或最大高度,则按比例缩放 - if (this._maxWidth.HasValue || this._maxHeight.HasValue) + // 得到页面宽高 + double pageWidth = 0; + double pageHeight = 0; + + var pageSize = mdXDoc.Descendants(W.sectPr).FirstOrDefault()?.Descendants(W.pgSz).FirstOrDefault(); + if (pageSize != null) { - var ratio = (float)w / h; - if (this._maxWidth.HasValue && this._maxHeight.HasValue) - { - if (ratio > (float)this._maxWidth.Value / this._maxHeight.Value) - { - w = this._maxWidth.Value; - h = (int)(w / ratio); - } - else - { - h = this._maxHeight.Value; - w = (int)(h * ratio); - } - } - else if (this._maxWidth.HasValue) + pageWidth = Convert.ToDouble(pageSize.Attribute(W.w.GetName("w")).Value) / 20; + pageHeight = Convert.ToDouble(pageSize.Attribute(W.w.GetName("h")).Value) / 20; + } + + // 得到设置宽高,传进来的参数 + int.TryParse(this._width, out var settingWidth); + int.TryParse(this._height, out var settingHeight); + + // 如果设置的宽度是百分比,那么按百分比计算宽度 + if (this._width != null && this._width.EndsWith("%")) + { + // 先计算比例,避免宽度变更后比例也跟着变化。 + var radio = imgWidth / (float)imgHeight; + double percent = Convert.ToDouble(this._width.TrimEnd('%')) / 100; + imgWidth = (int)(pageWidth * percent); + + // 如果没有设置高度,那么按比例计算高度 + if (this._height == null) { - w = this._maxWidth.Value; - h = (int)(w / ratio); + // 那么按比例计算高度 + imgHeight = (int)(imgWidth / radio); } - else + } + else if (settingWidth > 0) // 如果设置了宽度,那么按设置的宽度来 + { + imgWidth = settingWidth; + } + + // 如果度是百分比,那么按百分比计算高度 + if (this._height != null && this._height.EndsWith("%")) + { + // 先计算比例,避免宽度变更后比例也跟着变化。 + var radio = imgWidth / (float)imgHeight; + double percent = Convert.ToDouble(this._height.TrimEnd('%')) / 100; + imgHeight = (int)(pageHeight * percent); + + // 如果没有设置宽度,那么按比例计算宽度 + if (this._width == null) { - h = this._maxHeight.Value; - w = (int)(h * ratio); + // 那么按比例计算宽度 + imgWidth = (int)(imgHeight * radio); } } + else if (settingHeight > 0) // 如果设置了高度,那么按设置的高度来 + { + imgHeight = settingHeight; + } - var cx = (long)(w / dpi * 914400); - var cy = (long)(h / dpi * 914400); + // 换算成EMUS + var cx = (long)(imgWidth / dpi * 914400); + var cy = (long)(imgHeight / dpi * 914400); var drawing = cc.Descendants(W.drawing).FirstOrDefault(); if (drawing != null) @@ -185,6 +220,14 @@ private void UpdateImageMetrics(XElement cc) } } + // 按比例缩放图片的方法,传入图片原始宽度和高度,传入缩放后的宽度 + private static (int width, int height) ScaleImage(int originalWidth, int originalHeight, int scaledWidth) + { + var ratio = (float)originalWidth / originalHeight; + var scaledHeight = (int)(scaledWidth / ratio); + return (scaledWidth, scaledHeight); + } + /// <summary> /// 替换新图片 /// </summary> From c42056c9cd07e4313742357a493628d07125be13 Mon Sep 17 00:00:00 2001 From: "yitian.chen" <48295852@qq.com> Date: Thu, 18 May 2023 10:49:04 +0800 Subject: [PATCH 20/20] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OpenXmlPowerTools/OpenXmlPowerTools.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenXmlPowerTools/OpenXmlPowerTools.csproj b/OpenXmlPowerTools/OpenXmlPowerTools.csproj index ca1673d2..53c99d63 100644 --- a/OpenXmlPowerTools/OpenXmlPowerTools.csproj +++ b/OpenXmlPowerTools/OpenXmlPowerTools.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> - <Version>4.5.10.4</Version> + <Version>4.5.10.5</Version> <Authors>yitian.chen</Authors> <Company>yitian.chen</Company> <PackageId>OpenXmlPowerTools-HrRd</PackageId>