From 8dec7eaa6888f798c2e6812b99b421d930b774f0 Mon Sep 17 00:00:00 2001 From: "y.oshima" Date: Thu, 25 Mar 2021 13:59:40 +0900 Subject: [PATCH] =?UTF-8?q?Excel=E2=87=92Adoc=E5=A4=89=E6=8F=9B=E3=83=84?= =?UTF-8?q?=E3=83=BC=E3=83=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EcxelToAdocConverter.exe | Bin 0 -> 13312 bytes Tool/ExcelToAdocConverter/readme.txt | 20 + .../source/EcxelToAdocConverter.sln | 31 + .../source/EcxelToAdocConverter/App.config | 6 + .../EcxelToAdocConverter.csproj | 82 +++ .../ExcelToAdocConverter.cs | 547 ++++++++++++++++++ .../ExcelToAdocConverter.resx | 120 ++++ .../Properties/AssemblyInfo.cs | 36 ++ 8 files changed, 842 insertions(+) create mode 100644 Tool/ExcelToAdocConverter/EcxelToAdocConverter.exe create mode 100644 Tool/ExcelToAdocConverter/readme.txt create mode 100644 Tool/ExcelToAdocConverter/source/EcxelToAdocConverter.sln create mode 100644 Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/App.config create mode 100644 Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/EcxelToAdocConverter.csproj create mode 100644 Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.cs create mode 100644 Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.resx create mode 100644 Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/Properties/AssemblyInfo.cs diff --git a/Tool/ExcelToAdocConverter/EcxelToAdocConverter.exe b/Tool/ExcelToAdocConverter/EcxelToAdocConverter.exe new file mode 100644 index 0000000000000000000000000000000000000000..21244401e2f7de3f5f53447586214403d021c79d GIT binary patch literal 13312 zcmeHNdvF`)ao;-t2M`279w36EZJ7`y%8*DxA}Q-->OqN=L|YG9q+XF^=?EN2SO5;b z10>RxR64FbbsX1rr*0Cbj^jx)88weOaWaWtjq_}sHjdLKlR9x7Cz+1F_UrP1>2goja)oss^e>p%LA8xzb4q)Pm z!>gq2*eOuLw-Z1(K0Wx(>uN$L3aU2nf)!yj{w$gj{}>of6m((%fYS=l6<-KuN4sEKG3MCF2w5$tsc&eI z*PJ#KSnw{WCfWft>ncE3K@SwfoU2*l8i20&D{!n{4|>%d83}P^wh}&-zq441FHxOCTk*pw_clOEdv%^!F^4O8v4&r2!;saG7fi z2^(A?ar>EabjplxRv6IFcD7z(C!r+}4z|-&Yo}cQO%!gm6@?0kZkR72X37e>8oBt7 z(2v0Dt-;ntHGu&VY>P9a&FKXmvfEL|Ndj$(MZMjY?rl31^)~1}3*#Ud)pX6m{1fcC z2}mE1g;qbHH2}~NOsvK$>UWFUszvre_T+k$_V{#vu-l{i8?{)!=GXevS37m@IV6#{ zUwySLV6A~rSJc;g&#S>ej~1}jf__ESZnZF}Aj{d|n6n-*8qfpQ21XiQ4e5a%KS&|0 zH}DjpAm>$Tqj!FQf*^r^ff`?=5aT>1U&b3~~b)Vo# zfvDuE_In_P2(z_rr4>PjXs3=>-!*{Vl`&1#eM}#=HbN$`2_V=V(Nw?g_1E$|H#Rl| zHgC9i@uJ2t;Bf$@yawoA)njeuda?t1eZJU4>k6Oj#hC1>EhwL;;|zhr`R}C@(1T&9 ztDbWhR^A9DFu@`%V=L7KD^&Y&ZmD)iv>_CbOwdx+BVd7zFlP}bh-(vE608-UIF?pdv{*1|s z71E=E^aBWCc!K2NJ|D!q(7^pL3U`9iW7!W2Laj}$QEx2ji$yifZsoc+LTK5#htVz> zAGd?HfF0X(0ZCKG=CDNrl2tQ_L>nZ_%}CC_ItFVy)T9UO4w#fPN|Z-N;wILo!J&0$ zUPEG#nb<4ji4#r3w%^G5qQ zmcEke?{MX6>ivMps_NITpnBb>FKJzqrZ@f1`QG&3>APn0=qaZF7E7NV2(9}AG)U%c z-3(K#ou1W7OQk6FeVt92YQC7+9p17)e^=92G*MMk?rne*-k;>8? z4A9o51)=(>=)`|wai|%vnthRbM3~qI>p|P^p+eN(7S+2K=zhBclvr@EuIp%?jz{bN zAxgTdC0b1PC&p1*NLmxXmTA_0yu^Ht>4XngU5i)`CgXb z%(Xd71p~`3YQ)6K74@n1hd{ZDaa69mf+bg~@)8{NHy{EcXgqn#nVaWpF@6@_kFHg) zT@F6l)z;DUsC57`(S}$w*u7qF(1VY(l?67qWsT^^#@Hib=IKF)GNCuNJz^b1O+ARX z1L_TbnCbtlbBL8;^CM;h-D@2Nz3vEhQ2sXFn0yre2V`qPdMLJeCrb2?V7uFnklVAyp3r^pKlb;RfX0Z`a&r`%@gr=GY@LeOhFnA$>%jxm_n_5ZN)h z=sLFt>-gM*;8!NIvOISr_?4MR@|)i@(h)cisYY55dgO|c)&qKru8a8kwaxE)$Wk{$a;v9{6~ z&}q25WNVhKiw7Pn2V2!Z1Nijs$^hX|$JTKk;By!6J*gcZZ0m{Z;IPVb1NQY&4lNh* z(&Jk^@~zPe>Q8(ct?@AYweqa5nU?S*L|y7vy&8Q)!21PU*(lVc(1vq4#(+=sD-T16D?ScTkwxy=OIz2I&!S zj`{BKYxFtgQOLyn40mY^zoGoZ7bF`Rf;6fzJO%w4m3)tS@1pObc@a9`*Stackiw;Z zD`YkS*XSh=>->FK4ATbRS$Oq2EQaYZh3%$qocxlhnG1W#Bhy}*#cWZ z`lM*rpK9E$pTi0QOEv?|#ODc@I;ePDzCoriw1rC8*B}>LFUI z_*I3z;ZiU9L!e$+!u1}aPx~XPN?%+msn`AOs+U4tl6tRyi5j3;m-?2rTn*C1GFdj^ z9Z-=`*GcMAv`!7t&TdIPqlDBj&AU{{zf*0dg-KcV7v6(v3oRAYowOA_p;N)7zC*`U zoop$&@Podz8l?}rWeUoo^rTBQgKDK`Txt|l8-2m04uWc@zY)|!Ld(_kEkWHQB6u}@ zS5S9Rl4jJa;g&+Tqu&(zHg@$Yofr6v;H&fma1Sj4-%IP!k1WIdr-aN$Fk%(@g}^^5 z_&o5++P*081ETaKB%uvMQ_BA?cmq9#nNkPTFt#5<{x1h?K^`$&FW``XqXOP6;9&s` zz*fo#{5ApS1pGQ6MzMf*3aBW5z=>gAm^d6Ug8hC^9n6H-9C{w4djVSj+r5v{sPcVCK1I)IAE29+ z`@HArurlF!f(&I5eUdUtTi|KBO}R~Zg65PbF*1e}#rM3>^Cj?qO;14P6P|AaCSfHs&8z{uv&IMC&rjyL?XoZwxF@Li8iLN_mP}y`9Rvv{SiG$tVn8 z5Rxy@?aH`vr}6{;Veps0lNZPjPKfUF9#`&Fo>8Wh1p;3nw7mcgrxClmm2=Q=)cEs-N%(y-;0W(oWw{{lo_Q3@%%ePRZ-^rts+X_fCiTT z71`bb;F$7?lEi9YsY!~`Ea27jF2E)9e!y;e8gM|s8wA`Y_&3q>;ExN=5dl;558#|6 z)srNLnmsAHi;j6-Q|lC6ZrxK^d^!DOmv*_$ShA76cZ71dIG zG+~YAiv#^MxM@8X1E~@2r{PShn6dJPJ$ItMXrNATHBFnviFliXqEO*@mKF~fGu31c#APFO=} zD@DcGqImPYzL8EJ-(?wT8aHx-S*t0XrSXZO zi5VLW87g8&HCZa6l9elDvZgJ{GZZbPJ zktx=SR@kuiUE2Ta>R{#0v~3%6PMsmyfAHaNX5 zFCI3Xl$|Nm7s^J98vD$wF)J|V^2%d2(l1rKykMJEn6op}GgmCi6^#5`wa&g$zL?3G zY!h}S(O1QqQtr+JMz&JR z8iiuM1>`xJ42*CGI?>gfij`i=7}I&nDP~emnN{v}Oy8z$6~;~bR3>F!R$QJas^yg_ zGijTSRkFE~oF$MKn7BcX%ofnkW_qV+?rvk2r!A+_tRWkRI*fj&wxcVS4`%Xd>$H>P zS-HaG$t}6hoGxVz8`@!+rv(R7J>4{PGxK>pF=m&Xdby^WHFdIoK~KBV^&6#I2iG4iAO$$o5PFDE@RFr7121Slrvqz zOV~EK|H|*tU}YQFpB^mPtcm7yRIMuunCzZ9Cz44mDW^w>5{- zBGJZM5QTAIT)&9lCdeplpffZ=dFZKfmP7Igt)gC>U5;Vj3GZ63RFj$q;cXGSMvn0& z+`J9qX9jhghCx~kJvd$X8Ezs)$W(gt_TY?TGNEzVcLZ~^7mU6sH!XIiaf}Vvhz2I?%O+%B?JPmFhAI>z~ zFg0*|rXWR4DN(|;;D_fHXtzbJ87^IPO7M%|V6TXpbz1$Ltp(`Fp*)R0)=EvB(HMS! zIb1Id;_QqFwH<*5*}9GRwTdpq&N64uD}EcojnMxCN!gce-A8E&ni1_Ljyd;q12mBD2JRPs60t*k zd;%iJWIuAd%DGF|4Z>=59B-x#@WVk)ZbpvYf{Z$bpVA-;<{uaoX=@;8w}W{El^83h z@d_lmg~|m~O#o*lRRznT;tWEw@-6F-@-n#-aApGnzXI>&uqqOL{=!k@FOQ^KU~CqS zuq%x9p>_Q32S>j9-S=AeEz1WmA948rMyMQz?DPugWOEx)R;8+Tev{S#%ve%eRV&kL z;DywF2A4)s&vhcI%RzIX*wcQuMB*It<&~1sL9*&hamJ2K^(aEm_}2t*D?Mgrl;F(6?aSR?a~hH#-BnSUIZ z8c?Apax5$iormhk{0G@nNUDKw08kAJSA)U0r(CJQ?+*vW17}$(u7ZYa7_xq-)8Z<0 z2K;`XkP7*|tq}vIV1_k`!Yppf{Ag^Hq6!)iImT+j;Vyq9VsdRfAf>c~E)fv z3YK)6vzN^$nW42N;06&5JeAzC#8Nq-bZA|p~9=4#3og#-8xgcp@vSOg`? zqVOV*j}Z7F_B^c5e-nYz=U)zd`u3v-+E>4JZ{Uf|$A3@%W^jY51w2}01fNlSLio&i z5&ZqA9gghRI94rz2J)gUk&zY|JkW~tC5*;|!_6#J<5Sozc4gQR_6qqDxs5OGBziWW zxIZSmmM?fG)EIAx_gMLn*_0_ZYB-Bxf2TlB755AHjnINCoq{kSDJ;;YP^5D5ihurm zJl?;mAHNn_uF%qfHHNYF`u;V&Yx~Tp-qovCt?!-e?=yR^zus6iHMKf5W%Tvq8wZ8_ zefYuwe?+?#x+b}2WTJBN>~Rl18}X&Ynq(h*4lk$_@<}>t%<;K=0oRIGO5#G=D_q1a z8qteix$u`vJ%mrTa?WtK$k@C}Oz!)8;^m8so_N_jetm^VvB+sO9B z$4Zkp&0y0tVVyMd8zQHC0x;Tanm=708? zpYYY!ewg1ZayLFN;Y<6M@SRQV!{4{mKKsUp$3LL_cv?U8_j^A6#o3Oxl4q>k@7Q_70KKTVdOt}0^gHikd~h_p4C7P zU?+MUaD?^&8>PLp2lOc5cHsOx=e_WTymyqkBu-fQ$)&rW>jr{KJT8zrHQqfo%9p=ReRysziQ={&{p$NQOn_{l$+<``D>$e!dK zIiGQC>^;lTCVHD_$6nV4_awKY99yPjs^y3`q%PsLOd@#^Vz}8v$<>>R{(sgv9S|t zRcG9Eujw{+;$FOWU1uEk8u_%5#r46)&N`hs@4Th6Tp6ct2=Zt)2%5;k5g-6(fvUt3rY&4BK3Y_fgeB#xq zGoHs%xUqBhT+J0*(kK) + + + + + \ No newline at end of file diff --git a/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/EcxelToAdocConverter.csproj b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/EcxelToAdocConverter.csproj new file mode 100644 index 0000000..368e0f5 --- /dev/null +++ b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/EcxelToAdocConverter.csproj @@ -0,0 +1,82 @@ +サソ + + + + Debug + AnyCPU + {36AA7526-71EF-4009-B21E-55A0FF4CFA12} + Exe + EcxelToAdocConverter + EcxelToAdocConverter + v4.6.1 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + Form + + + + + + + + + ExcelToAdocConverter.cs + + + + \ No newline at end of file diff --git a/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.cs b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.cs new file mode 100644 index 0000000..e979fd9 --- /dev/null +++ b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.cs @@ -0,0 +1,547 @@ +サソusing System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +class SampleForm : Form +{ + static readonly int ExpectedHeaderMaxLines = 20; + static readonly Regex rxTableBeginTag = new Regex(@"]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase); + // 1 2 3 *?縺ッ譛遏ュ繝槭ャ繝 o:p縺ッMS office(word)蟇セ遲 + static readonly Regex rxTag = new Regex(@"<([a-z][a-z0-9]*|o:p)(|\s[^>]*)>||", RegexOptions.Multiline | RegexOptions.IgnoreCase); + //static readonly Regex rxTag = new Regex(@"<([a-z][a-z0-9]*)(|\s[^>]*)>||", RegexOptions.Multiline | RegexOptions.IgnoreCase); + + + TextBox txtAdoc; + + SampleForm() + { + Text = "HTML table(Clipborad) to AsciiDoc"; + ClientSize = new Size(700, 430); + + var btn = new Button() + { + Size = new Size(280, 25), + Text = "Get AsciiDoc from Clipborad", + }; + btn.Click += (s, e) => { ParseFromHtmlClipboard(); }; + Controls.Add(btn); + + var btnDbg = new Button() + { + Location = new Point(300, 0), + Size = new Size(220, 25), + Text = "Get HTML from Clipborad(髢狗匱閠逕ィ)", + }; + btnDbg.Click += (s, e) => { DumpHtmlClipboard(); }; + Controls.Add(btnDbg); + + txtAdoc = new TextBox() + { + Location = new Point(0, 30), + Size = new Size(700, 400), + Text = "", + Multiline = true, + WordWrap = false, // 謚倥j霑斐@陦ィ遉コ繧偵@縺ェ縺 + ScrollBars = ScrollBars.Both, + }; + Controls.Add(txtAdoc); + txtAdoc.KeyDown += (s, e) => { if (e.Control && e.KeyCode == Keys.A) { ((TextBox)s).SelectAll(); } }; + + Resize += (s, e) => { MyResize(); }; + ResizeEnd += (s, e) => { MyResize(); }; + } + + void MyResize() + { + int h = ClientSize.Height - txtAdoc.Top; + if (h < 50) { h = 50; } + txtAdoc.Size = new Size(ClientSize.Width, h); + } + + void ParseFromHtmlClipboard() + { + MemoryStream ms = GetHtmlClipboard(); + if (ms != null) + { + string tmp = Parse(ms); + if (tmp != null) + { + txtAdoc.Text = tmp; + txtAdoc.Focus(); + txtAdoc.SelectAll(); + } + else + { + txtAdoc.Text = "Parse Failed"; + } + } + else + { + txtAdoc.Text = "Clipboard Load failed"; + } + } + + void DumpHtmlClipboard() + { + MemoryStream ms = GetHtmlClipboard(); + if (ms != null) + { + string tmp = GetHtmlText(ms); + if (tmp != null) + { + txtAdoc.Text = tmp; + //txtAdoc.Focus(); + //txtAdoc.SelectAll(); + } + else + { + txtAdoc.Text = "Parse Failed"; + } + } + else + { + txtAdoc.Text = "Clipboard Load failed"; + } + } + + static MemoryStream GetHtmlClipboard() + { + return Clipboard.GetData("Html Format") as MemoryStream; + } + + static string GetHtmlText(MemoryStream ms) + { + int startHtml = -1; + int endHtml = -1; + + // 繝倥ャ繝諠蝣ア(StartHTML, EndHTML)繧貞叙蠕 + // StartHTML:nnnnnnnnnn + // EndHTML:nnnnnnnnnn + //public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen) + // leaveOpen=true縺ァ髢九°縺ェ縺縺ィ縲[s縺碁哩縺倥※縺励∪縺縲 + using (var sr = new StreamReader(ms, Encoding.UTF8, true, 1024, true)) + { + Regex rx = new Regex(@"^(StartHTML:|EndHTML:)([0-9]+)"); + int lineCount = 0; + string s; + while ((s = sr.ReadLine()) != null) + { + lineCount++; + Match m = rx.Match(s); + if (m.Success) + { + int n = Convert.ToInt32(m.Groups[2].Value, 10); // 10騾イ + if (m.Groups[1].Value == "StartHTML:") + { + startHtml = n; + } + else + { + endHtml = n; + } + if (startHtml >= 0 && endHtml > startHtml) + { + break; + } + } + if (lineCount >= ExpectedHeaderMaxLines) + { + break; + } + } + } + + // HTML驛ィ蛻繧貞叙蠕(EndHTML縺ッ辟。隕) + ms.Position = startHtml; + using (var sr = new StreamReader(ms, Encoding.UTF8, false)) + { + return sr.ReadToEnd(); + } + } + + // stype繧ソ繧ー縺ョ荳ュ霄ォ繧定ソ斐☆ + static string GetStyleText(string htmlText, out int endPos) + { + string retString = null; + + endPos = 0; + int styleStartTagPos = 0; + int maxStyleTag = 50; + int styletagCounter = 0; + + while (styletagCounter < maxStyleTag) + { + styletagCounter++; + styleStartTagPos = htmlText.IndexOf("", styleStartTagPos); + if (styleEndTagPos < 0) + { + break; + } + endPos = styleEndTagPos + "".Length; + + int commentStartTagPos = htmlText.IndexOf("", commentStartTagPos); + if (commentStartTagPos >= 0 && commentEndTagPos > commentStartTagPos && commentEndTagPos < styleEndTagPos) + { + // 繧ウ繝。繝ウ繝医ち繧ー縺後≠繧句エ蜷医√さ繝。繝ウ繝医ち繧ー繧帝勁蜴サシ医さ繝。繝ウ繝医ち繧ー蜀縺ョ縺ソ繧定ソ斐☆シ + retString += htmlText.Substring(commentStartTagPos, commentEndTagPos - commentStartTagPos); + } + else + { + // 繧ウ繝。繝ウ繝医ち繧ー縺後↑縺蝣エ蜷 + retString += htmlText.Substring(styleStartTagPos, styleEndTagPos - styleStartTagPos); + } + styleStartTagPos = endPos; + } + return retString; + } + + static int IndexOfUsingRegex(string src, int startPos, Regex rTarget, out int length) + { + Match m = rTarget.Match(src, startPos); + if (!m.Success) + { + length = 0; + return -1; + } + length = m.Groups[0].Length; + return m.Groups[0].Index; + } + + // table繧ソ繧ー霎シ縺ソ縺ァ霑斐☆ + // 繝阪せ繝医ッ險ア螳ケ縺励↑縺(讀懷コ縺励※null繧定ソ斐☆) + static string GetFirstTableText(string htmlText, int pos) + { + int len; + int tableStartTagPos = IndexOfUsingRegex(htmlText, pos, rxTableBeginTag, out len); + if (tableStartTagPos < 0) + { + return null; + } + + int tableEndTagPos = htmlText.IndexOf("", tableStartTagPos + len); + if (tableEndTagPos < 0) + { + return null; + } + int dummy; + int tmpPos = IndexOfUsingRegex(htmlText, tableStartTagPos + len, rxTableBeginTag, out dummy); + + if (tmpPos >= 0 && tmpPos < tableEndTagPos) + { + // 繝阪せ繝医@縺ヲ縺繧具シ磯哩縺倥ち繧ー繧医j繧よ焔蜑阪ョ菴咲スョ縺ォ2縺、逶ョ縺ョ髢句ァ九ち繧ー繧呈、懷コ縺励◆シ + return null; + } + + tableEndTagPos += "".Length; + return htmlText.Substring(tableStartTagPos, tableEndTagPos - tableStartTagPos); + } + + + //static readonly Regex rxCss = new Regex(@":;", RegexOptions.Multiline | RegexOptions.IgnoreCase); + + //static Dictionary> ParseCssPart(string styleText) + //{ + //} + + // https://momdo.github.io/html/syntax.html#attributes-2 + // 螻樊ァ蜷阪ッ縲∝宛蠕。譁蟄励ゞ+0020 SPACE縲ゞ+0022シ"シ峨ゞ+0027シ'シ峨ゞ+003Eシ>シ峨ゞ+002Fシ/シ峨ゞ+003Dシ=シ峨√♀繧医ウ髱樊枚蟄嶺サ・螟悶ョ1縺、莉・荳翫ョ譁蟄励〒讒区舌&繧後↑縺代l縺ー縺ェ繧峨↑縺縲HTML讒区枚縺ォ縺翫>縺ヲ縲∝、匁擂隕∫エ縺ォ蟇セ縺吶k繧ゅョ縺ァ縺輔∴縲∝ア樊ァ蜷阪ッ縲、SCII蟆乗枚蟄励♀繧医ウASCII螟ァ譁蟄励ョ莉サ諢上ョ邨縺ソ蜷医o縺帙〒譖ク縺九l縺ヲ繧ゅh縺縲 + // 螻樊ァ蛟、縺ッ縲√ユ繧ュ繧ケ繝医′譖匁乂縺ェ繧「繝ウ繝代し繝ウ繝峨r蜷ォ繧√k縺薙→縺後〒縺阪↑縺霑ス蜉縺ョ蛻カ髯舌r繧ゅ▽蝣エ蜷医r髯、縺阪√ユ繧ュ繧ケ繝医♀繧医ウ譁蟄怜盾辣ァ縺ョ豺キ蜷育黄縺ァ縺ゅk縲 + // 蠑慕畑隨ヲ縺ァ蝗イ縺セ繧後↑縺螻樊ァ蛟、讒区枚 + // ASCII遨コ逋ス譁蟄 U+0022 QUOTATION MARK譁蟄暦シ"シ峨 + // U+0027 APOSTROPHE譁蟄暦シ'シ峨ゞ+003D EQUALS SIGN譁蟄暦シ=シ峨 + // U+003C LESS-THAN SIGN譁蟄暦シ<シ峨ゞ+003E GREATER-THAN SIGN譁蟄暦シ>シ峨 + // 縺セ縺溘ッU+0060 GRAVE ACCENT譁蟄暦シ`シ画枚蟄励r蜷ォ繧薙〒縺ッ縺ェ繧峨★縲√°縺、遨コ譁蟄怜励〒縺ゅ▲縺ヲ縺ッ縺ェ繧峨↑縺縲 + + // 1 = 2 3 4 + // <-------------------------------------> <--------------------------------> <-----> <-------> + // <----------------------------------------------------------------> + static readonly Regex rxAttr = new Regex(@"\b([^\x00-\x1F\x20\x22\x27\x2F\x3D\x3E]+)\s*(?:=\s*(?:([^\x20\x22\x27\x3C\x3D\x3E\x60]+)|'([^']*)'|\x22([^x22]*)\x22))?", RegexOptions.Multiline | RegexOptions.IgnoreCase); + + static Dictionary ParseAttrs(string attrsStr) + { + var dict = new Dictionary(); + + Match mAttr = rxAttr.Match(attrsStr); + while (mAttr.Success) + { + string key = mAttr.Groups[1].Value.ToLower(); + + string value = ""; + if (mAttr.Groups[2].Length > 0) + { + value = mAttr.Groups[2].Value; + } + else if (mAttr.Groups[3].Length > 0) + { + value = mAttr.Groups[3].Value; + } + else if (mAttr.Groups[4].Length > 0) + { + value = mAttr.Groups[4].Value; + } + else + { // without "=" + // do nothing + } + + if (!dict.ContainsKey(key)) + { + dict.Add(key, value); + } + + mAttr = mAttr.NextMatch(); + } + return dict; + } + + static string EscapeContentForAdocTableCell(string s) + { + // Replace (string input, string replacement); + s = rxTag.Replace(s, ""); // HTML蜈ィ闊ャ縺ョ繧ソ繧ー繧呈カ亥悉 + s = s.Replace("\r\n", " ") + .Replace("\n", " ") + .Replace("\r", " ") + .Replace("\t", " ") + .Replace(" ", " ") + .Replace("<", "<") + .Replace(">", ">") + .Replace("&", "&") + .Replace("|", "{VBar}"); // ADoc逕ィ + return s; + } + + static string ParseTableToAdoc(string tableText, Dictionary> classFormat) + { + var sb = new StringBuilder(); + Match m = rxTag.Match(tableText); + string lastStartTag = null; + int lastPos = -1; + int lastTdPos = -1; + int currentTdCount = 0; + int maxTdCount = 0; + + sb.AppendLine("|==="); + + while (m.Success) + { + if (m.Groups[1].Length > 0) + { + string tag = m.Groups[1].Value; + string attrsStr = m.Groups[2].Value; + lastPos = m.Groups[0].Index + m.Groups[0].Length; + + if (tag == "tr") + { + maxTdCount = Math.Max(maxTdCount, currentTdCount); + currentTdCount = 0; + } + else if (tag == "td") + { + lastTdPos = lastPos; + if (lastStartTag != "tr") + { + sb.Append(" "); + } + var attrs = ParseAttrs(attrsStr); + if (attrs.ContainsKey("colspan") || attrs.ContainsKey("rowspan")) + { + if (attrs.ContainsKey("colspan")) + { + sb.Append(attrs["colspan"]); + currentTdCount = currentTdCount + int.Parse(attrs["colspan"])-1; + } + if (attrs.ContainsKey("rowspan")) + { + sb.Append("."); + sb.Append(attrs["rowspan"]); + } + sb.Append("+"); + } + if (attrs.ContainsKey("class")) + { + var format = classFormat["default"]; + string classid = attrs["class"]; + if (classFormat.ContainsKey(classid)){ + format = classFormat[classid]; + } + sb.Append(format["text-align"].Replace("general", "<").Replace("left", "<").Replace("center", "^").Replace("right", ">")); + sb.Append("."); + sb.Append(format["vertical-align"].Replace("general", "<").Replace("top", "<").Replace("middle", "^").Replace("bottom", ">")); + } + else + { + var format = classFormat["default"]; + sb.Append(format["text-align"].Replace("general", "<").Replace("left", "<").Replace("center", "^").Replace("right", ">")); + sb.Append("."); + sb.Append(format["vertical-align"].Replace("general", "<").Replace("top", "<").Replace("middle", "^").Replace("bottom", ">")); + } + sb.Append("|"); + currentTdCount++; + } + lastStartTag = tag; + } + else if (m.Groups[3].Length > 0) + { + string tag = m.Groups[3].Value; + int tagStartPos = m.Groups[0].Index; + //Console.WriteLine(""); + if (tag == "tr") + { + sb.AppendLine(""); + } + else if (tag == "td") + { + string s = tableText.Substring(lastTdPos, tagStartPos - lastTdPos); + sb.Append(EscapeContentForAdocTableCell(s)); + lastTdPos = -1; + } + lastPos = -1; + lastStartTag = null; + } + + m = m.NextMatch(); + } + + sb.AppendLine("|==="); + + //謨エ蠖「 + sb = sb.Replace("<.<", ""); + string firstLine = "[cols=\"<.> classFormat = GetFormat(styleText); + string tableText = GetFirstTableText(htmlText, pos); + return ParseTableToAdoc(tableText, classFormat); + } + + static Dictionary> GetFormat(string styleText) + { + int maxFormatNum = 100; + int counter = 0; + int endPos = 0; + Regex reg = new Regex(@"[\t {};]"); + + // 繝繝輔か繝ォ繝亥、縺ョ繝繝輔か繝ォ繝亥、 + var dctDefault = new Dictionary(); + dctDefault.Add("color", "black"); + dctDefault.Add("background", "black"); + dctDefault.Add("text-align", "left"); + dctDefault.Add("vertical-align", "top"); + + // 繝繝輔か繝ォ繝亥、蜿門セ + int startTdTagPos = styleText.IndexOf("td\r\n\t{", 0); + int endTdTagPos = styleText.IndexOf(";}", startTdTagPos); + string defauletFromatText= styleText.Substring(startTdTagPos, endTdTagPos + ";}".Length-startTdTagPos); + var defaultLines = reg.Replace(defauletFromatText, "").Replace("\r\n", "\n").Split(new[] { '\n', '\r' }); + foreach (string line in defaultLines) + { + string[] words = line.Split(':'); + if (dctDefault.ContainsKey(words[0])) + { + dctDefault[words[0]] = words[1]; + } + } + + var ret = new Dictionary>(); + ret.Add("default", dctDefault); + + // 蜷繧ッ繝ゥ繧ケ縺ョ譖ク蠑上r蜿門セ + while (counter < maxFormatNum) + { + counter++; + + int formatStartTagPos = styleText.IndexOf(".xl", endPos); + if (formatStartTagPos < 0) + { + break; + } + formatStartTagPos += ".xl".Length; + + int formatEndTagPos = styleText.IndexOf(";}", formatStartTagPos); + if (formatEndTagPos < 0) + { + break; + } + endPos = formatEndTagPos + ";}".Length; + + string formatText = styleText.Substring(formatStartTagPos, endPos - formatStartTagPos); + var lines = reg.Replace(formatText, "").Replace("\r\n", "\n").Split(new[] { '\n', '\r' }); + + string classid = "xl" + lines[0]; + var dctFormat = new Dictionary(); + dctFormat.Add("color", dctDefault["color"]); + dctFormat.Add("background", dctDefault["background"]); + dctFormat.Add("text-align", dctDefault["text-align"]); + dctFormat.Add("vertical-align", dctDefault["vertical-align"]); + + foreach (string line in lines) + { + string[] words = line.Split(':'); + if (dctFormat.ContainsKey(words[0])) + { + dctFormat[words[0]] = words[1]; + } + } + ret.Add(classid, dctFormat); + } + return ret; + } + + [STAThread] + static void Main(string[] args) + { + Application.Run(new SampleForm()); + } + + private void InitializeComponent() + { + this.SuspendLayout(); + // + // SampleForm + // + this.ClientSize = new System.Drawing.Size(284, 261); + this.Name = "SampleForm"; + this.Load += new System.EventHandler(this.SampleForm_Load); + this.ResumeLayout(false); + + } + + private void SampleForm_Load(object sender, EventArgs e) + { + + } +} \ No newline at end of file diff --git a/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.resx b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.resx new file mode 100644 index 0000000..29dcb1b --- /dev/null +++ b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/ExcelToAdocConverter.resx @@ -0,0 +1,120 @@ +サソ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/Properties/AssemblyInfo.cs b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..864bbc6 --- /dev/null +++ b/Tool/ExcelToAdocConverter/source/EcxelToAdocConverter/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +サソusing System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 繧「繧サ繝ウ繝悶Μ縺ォ髢「縺吶k荳闊ャ諠蝣ア縺ッ莉・荳九ョ螻樊ァ繧サ繝繝医r縺ィ縺翫@縺ヲ蛻カ蠕。縺輔l縺セ縺吶 +// 繧「繧サ繝ウ繝悶Μ縺ォ髢「騾」莉倥¢繧峨l縺ヲ縺繧区ュ蝣ア繧貞、画峩縺吶k縺ォ縺ッ縲 +// 縺薙l繧峨ョ螻樊ァ蛟、繧貞、画峩縺励※縺上□縺輔>縲 +[assembly: AssemblyTitle("EcxelToAdocConverter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EcxelToAdocConverter")] +[assembly: AssemblyCopyright("Copyright ツゥ 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible 繧 false 縺ォ險ュ螳壹☆繧九→縲√%縺ョ繧「繧サ繝ウ繝悶Μ蜀縺ョ蝙九ッ COM 繧ウ繝ウ繝昴シ繝阪Φ繝医°繧 +// 蜿らァ縺ァ縺阪↑縺上↑繧翫∪縺吶COM 縺九i縺薙ョ繧「繧サ繝ウ繝悶Μ蜀縺ョ蝙九↓繧「繧ッ繧サ繧ケ縺吶k蠢隕√′縺ゅk蝣エ蜷医ッ縲 +// 縺昴ョ蝙九ョ ComVisible 螻樊ァ繧 true 縺ォ險ュ螳壹@縺ヲ縺上□縺輔>縲 +[assembly: ComVisible(false)] + +// 縺薙ョ繝励Ο繧ク繧ァ繧ッ繝医′ COM 縺ォ蜈ャ髢九&繧後k蝣エ蜷医∵ャ。縺ョ GUID 縺 typelib 縺ョ ID 縺ォ縺ェ繧翫∪縺 +[assembly: Guid("36aa7526-71ef-4009-b21e-55a0ff4cfa12")] + +// 繧「繧サ繝ウ繝悶Μ縺ョ繝舌シ繧ク繝ァ繝ウ諠蝣ア縺ッ谺。縺ョ 4 縺、縺ョ蛟、縺ァ讒区舌&繧後※縺縺セ縺: +// +// 繝。繧ク繝」繝シ 繝舌シ繧ク繝ァ繝ウ +// 繝槭う繝翫シ 繝舌シ繧ク繝ァ繝ウ +// 繝薙Ν繝臥分蜿キ +// Revision +// +// 縺吶∋縺ヲ縺ョ蛟、繧呈欠螳壹☆繧九°縲∵ャ。繧剃スソ逕ィ縺励※繝薙Ν繝臥分蜿キ縺ィ繝ェ繝薙ず繝ァ繝ウ逡ェ蜿キ繧呈里螳壹↓險ュ螳壹〒縺阪∪縺 +// 譌「螳壼、縺ォ縺吶k縺薙→縺後〒縺阪∪縺: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] -- 2.22.0