From 10c2768f1aa297beeb349dd27c7a454bc4aabe90 Mon Sep 17 00:00:00 2001 From: walon Date: Sat, 19 Jun 2021 16:22:10 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9EExcel2TextDiff=E5=B7=A5=E5=85=B7=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=B0=86excel=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E4=B8=BAtext=E6=88=96=E8=80=85=E7=9B=B4=E6=8E=A5=E5=B0=86?= =?UTF-8?q?=E4=B8=A4=E4=B8=AAexcel=E6=96=87=E4=BB=B6=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E4=B8=BAtext=E5=90=8E=E5=86=8Ddiff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + config/Datas/test/full_type.xlsx | Bin 12409 -> 12485 bytes src/Excel2TextDiff/Excel2TextDiff.csproj | 13 ++++ src/Excel2TextDiff/Excel2TextWriter.cs | 61 +++++++++++++++ src/Excel2TextDiff/Program.cs | 90 +++++++++++++++++++++++ src/Luban.sln | 6 ++ 6 files changed, 171 insertions(+) create mode 100644 src/Excel2TextDiff/Excel2TextDiff.csproj create mode 100644 src/Excel2TextDiff/Excel2TextWriter.cs create mode 100644 src/Excel2TextDiff/Program.cs diff --git a/.gitignore b/.gitignore index 2dd2119..0682222 100644 --- a/.gitignore +++ b/.gitignore @@ -269,3 +269,4 @@ __pycache__/ /config/output_data /config/output_lua /config/output_lua_without_test +/src/Excel2TextDiff/Properties/launchSettings.json diff --git a/config/Datas/test/full_type.xlsx b/config/Datas/test/full_type.xlsx index bb5374a38d95ddc1ae8946c988d67cab5badf216..fee10bc567226a54dcc4e7a4e10ef4d0d44bdbf5 100644 GIT binary patch delta 4702 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 delta 4637 zcmZ8lXHXOB(hf++2qGP6(gK7ay%VIWbTIVZ2?V7|F$9n%f*^sYAQ*(uLN#DS`k_jd zE(k;+9Ha=+ivh0Ze)rDY`S!;?`|j+{zPmfKGrK+RCvJ87bd1g0rEVB%0Du;KMkj`P zjVsbG0qv*Q_?t|9`G#W);V0JL-W-bXySjuTsUaM&vX|dZkDR<7B`qM^_MV!;-qP1( zSjhK~MLSZBOGAWhCC~R_mJa0PF$1qLcX!#LA&+J0T-#sQ=C-+l!ZQIndF))%(@(bf zY<{KXU4w-(7UIS^8r{}&@56`vgP2ew2-vARYj>6ri3JSC=URGUPBWm99{9&S5=F-v4aaC7TRobYo~n zcZ7%C6MJc6DD#t1=eOgy(GI#pf(&C)?o*2tv?2$b3poLgs=_F@Y<2{swNY`;zfJhj zluW_J;>k$XYT_#AQs;?P4#h{>S%2eHqS^^}H~lVrQk9M=hY5Fkg5v@j~^_3}|O+C+l9wYD1)sh-v~G?*Ox&7d=K z(|cKH?{rp_@6ACB`n&z%<<1|f?rF;Jzf4WvDpO6+6=gajH2l@5R^IW-FI3vAW?Cpac0Q$CK;x^3@XL+q80iql4h%tPt`@oK0Rwom z83kP>Z;j52t|xW)TsU8Mw%f;0AS-L0Kg3Z03rirAKniM2=(*! z4hxn2H^@OE5rMDsokQpP*^;-3@QX{h-vBmJ&JJg9XN0aubfK=f$==lJnvrr=l8WwBKB%{kNS#Mubm&LEEJF4V$u_sL$+ zxz7*9>`7AfnP~&F_{gYG@VV;68IdppIxp0uy)`Gq((JXQiCc@Ehl}CM+%_bJ{RB5t zHT8F<&DYv@Jf&y*;@d~k-{)gyf{q*=q4R2UU8>qWM*F{5YZ3nYCV{%CD4De{ZUvhqisAIJ8*Rgaedv5sK;8)g2!m!WM&{|yOm*1e%8u0xeua#-< z$TM?vyW+kZV@J*ZxHBHTX91QqEOrU&UE$(DXja@u%ZG)G& zl&wk8<5xv9-iv1km^5Bp(NK76>q)+nSJ3HRTqE~(X5KGyGS$iF`41&QfsEsh&!@d{ zE_$}u zgzTB)7Rf$aV}35$=If@fGCakK=+Ho`)=y=XNKFTA*Fq)tg=N~8`Qcy%VpIuyFEMN& zF|x}ieD-~VnY_EpX$2~l)2J5cpjSc3Zmm_%*06ad6>dmvy=pe4E*H$^!00ma)wh}} z`)HufIKQcXG6ZGyC5kp+j5RITLguyRGiLRsUo)L{3i;u)+=ywt!)YI+a%?^@%Xv01 zb#u-~#7jjv)Lx!M6?tRe__N2bsV4UQPafwkTM-ccUW^|OT;XGvw| z*qf}TBIlYZ?2Xg-8%_y&m?>H1eLI_WYOmlnDlhv2T~tpLxZ1j0EpsJ2nz7K{qs-!= zz~E-smG|IA>vFBkl?bM()p~u?qH}eywKb^Yit!Y?RGqbmAH1|o7918L=~v?y=QIvz zDy0gsyhN^~>-Pp`ZOkP*7tSzaHERiv_jiSmF}#bQa_x`=4LN)lO29o#*$~K=RN$fako9hek*sGkYwPV*Q#_00!Ox~t>I;i*{V$Fl(xJ`6j@zz) zFFzO-RQwI__YmAJmg5J`1|q4Y#WP0%_DLkv+=FiL_9Tt@b;nCV`D%6v4>5_dfLZof z+I}12ef5R~?dTSyQ{1IRZ4=YAr>z3_1@FPU)ecYOk2pcDfB&u1<3W=n3!2f1!s9#$ zhCPllQ+Wn|D`|_W)6$sTDft4Ew5hk`1g#DTJ#1#?{(&W?x=DNeS@L6L<6cy* zVTt;<&0(hGv})ix#f2{rE#jTFl%GX2K7?blH`6~WIO6Zv7OSvxcIx8Hkt-G?L8qBL z^@1Sc%m$(27>h2Jt{q*^-n!{Ez5itFM54~);B+?mk}?lb`Fed?^MvPnB~1@KhlEf} z*`Kubkx6odK;*=81S89b>yQqO7pShwpcj{>?CpPDg3wp0Jl(}TULSe;Xbn3~0J*By zAk@jm^trD78h-#*U~n?NBk(7&th$eSF_nq3Kgg%0c=zxLej8NGIoz~ZW|qc#qoCP=6!I>s9*=% z1$R=D6B>(HtMc4pQMp4_Z8Y0X^?)W1s*s-b&nb>zRn|0GDfR&C3OlTBy-t!xJW~%f z$3H6Od!Xsku5nI>D&tH8^A}a>%`Svwo2MA;M{Y6+foB;VcE>ql>hRa6m{g#*q==$Z z2~Ej^;rrYMZVp-pW{-LREFnWqfEkzMzpbhrUC5L?bn$M zHo7RB5ZZyZ%QjBxtK}|Zz3+9$Xe%rmzH_A2h&+9y8lIM%&S=0#~-uQH%W^QD{LH2 z2NAe%(1F1VpbIFCHd+Z#Aq&$0nspe_3HfqC;-xj#2}`k3GdiGFde1>Eb2~!^Sj+0i zZ%^*3xCZhvVVL|-%?kR$7*EYX4GT@9PTEUC>BKYr^PH-G7WUr|PQw3@sEp&OG5`6+ zWbbq_Ejwu87KJu`?uf5vLcn%{H$I}0wvvT#Cm)S>!Y<`~5zu>Mx*8s2S7f&Qu3}5W zR&(c*jP#^GnAV=G9KN0y#u&~^4gxB@dj?-O|%H5^en)8|l#S2Ik9(PWL7{_k;8&M#61{!<$mj)he zL+J!5$8z&x89+pf4PV~c4y;N=%Xiz~I3gnFefGSOB*JCn;z+-pi}kaO>Rjf!MG0v5 z!jrN{x3|1-T!YRrey!kY+fg0oS_pg8U5xAjymw~~Pe<5ad zMD1wAsTqmL>+VhTzCrfy69x7u+RZJW-CWpsDY($qRFB}*9d9uAEPSW;OwIGJ7S5L6 zW{wR0Akw|Cp`siS(tCsZ{cKXakGic6ygLYqcMtM@&U)m?&2j1Vda-@2Sq_|K1X@r0 z*a?=>DBXxca|%nMT$4yuu^SO9f!!Y$q_oB2KEy@F=}^|hzXVc+aAYC$KVET@8RE@g z*h>6n!?2aq;UoS{g^I`+dFQr}F3k-iR<(rwt66+hP5;MOd9E@PK-FIfYQB0y(I%lR zSI#y+`JU`}R&k>qiWglkE0j&vMB8b`zP#~q4KMH&kK*1C-|I;|yth{YVFTyiRJfVG zhJmK4^?+>8v<0_&vn~(ItK%JQZ`#vKgq3{%Xnr#43NdR_`~CCQ`Pu4TGYglIIbLH3 z6&>An(X;g99RKrgN^`C2d9XS(nl22ATD)iJa(?=lO$<5@MNt?Y)17p6Q5MUd3JTs^ z;3^~ijY?@B%4Bho$>0NjSHWthcrsPeY{OniA!R(`Q9!aoA+3_x>*RnY;OH)|>C+ED zkjpr{QTg>xAkm+-@1etbh0m>sd44~MT%BP!Q{uo3=Cdtt;`F$Xc)5($wl^2DNY~3f}oB5X_-PyBEZs&8ZJB$Cd<$a?>QBosv`0@?qW_J34cJR@`j4VrTBSk^0*lJ8L zN9xPEGn6>Vvhzf)s6G$>#HPB>vyjKi6rCc%Z|^)lXyIb**;6-s7sO~?$l+}XmU`^{ zq=IHK3n;@vxX89YBH2wMN;xSTwa+fz3=Mi7%Sdyjp`xT)yjQ5D2RF742=X%Y88fKc zW)~w~!vV#rdowMOfd_;$k$EZ_T{-_I!h)Cr6$-)IxTNdoe&vlg13qw5M$}d&U_8qU zfBqX+9g&-%wHRa87PBR`wkwMN#+)t_kSomA0|N8}SXSyKNA##WVLQ}IY4C7b9`(lt zgOqc~O5W~V$Mhs`x^yR9VF`FeUC(G$vFFRK$Za2yZ3~zA8AJJ19#)Y(X)!|8sBoDq}`fftG^E@csWy_s_EX zADTypKn$oCInYfIDD^lW`V=B~{hwJ#yaWKmUIhTy|7-YfoDf7S$?8zIh@c + + + Exe + net5.0 + + + + + + + + diff --git a/src/Excel2TextDiff/Excel2TextWriter.cs b/src/Excel2TextDiff/Excel2TextWriter.cs new file mode 100644 index 0000000..ac5336c --- /dev/null +++ b/src/Excel2TextDiff/Excel2TextWriter.cs @@ -0,0 +1,61 @@ +using CommandLine; +using ExcelDataReader; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Excel2TextDiff +{ + class Excel2TextWriter + { + class CommandLineOptions + { + [Option('p', "port", Required = false, HelpText = "listen port")] + public int Port { get; set; } = 8899; + } + + public void TransformToTextAndSave(string excelFile, string outputTextFile) + { + var lines = new List(); + using var excelFileStream = new FileStream(excelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + string ext = Path.GetExtension(excelFile); + using (var reader = ext != ".csv" ? ExcelReaderFactory.CreateReader(excelFileStream) : ExcelReaderFactory.CreateCsvReader(excelFileStream)) + { + do + { + lines.Add($"===[{reader.Name ?? ""}]==="); + LoadRemainRows(reader, lines); + } while (reader.NextResult()); + } + File.WriteAllLines(outputTextFile, lines, System.Text.Encoding.UTF8); + } + + private void LoadRemainRows(IExcelDataReader reader, List lines) + { + int rowIndex = 0; + while (reader.Read()) + { + ++rowIndex; // 第一行是 meta ,跳过 + var row = new List(); + for (int i = 0, n = reader.FieldCount; i < n; i++) + { + object cell = reader.GetValue(i); + row.Add(cell != null ? cell.ToString() : ""); + } + int lastNotEmptyIndex = row.FindLastIndex(s => !string.IsNullOrEmpty(s)); + if (lastNotEmptyIndex >= 0) + { + row = row.GetRange(0, lastNotEmptyIndex + 1); + } + else + { + row.Clear(); + } + lines.Add(string.Join(',', row)); + } + } + } +} diff --git a/src/Excel2TextDiff/Program.cs b/src/Excel2TextDiff/Program.cs new file mode 100644 index 0000000..4cd89f7 --- /dev/null +++ b/src/Excel2TextDiff/Program.cs @@ -0,0 +1,90 @@ +using CommandLine; +using CommandLine.Text; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Excel2TextDiff +{ + class CommandLineOptions + { + [Option('t', SetName = "transform", HelpText = "transform excel to text file")] + public bool IsTransform { get; set; } + + [Option('d', SetName = "diff", HelpText = "transform and diff file")] + public bool IsDiff { get; set; } + + [Option('p', SetName = "diff", Required = false, HelpText = "3rd diff program. default TortoiseMerge")] + public string DiffProgram { get; set; } + + [Value(0)] + public IList Files { get; set; } + } + + class Program + { + static void Main(string[] args) + { + //if (args.Length != 2 && args.Length != 3) + //{ + // Console.WriteLine("Usage:"); + // Console.WriteLine("Excel2TextDiff [path_of_diff_program]"); + // return; + //} + + var options = ParseOptions(args); + + System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); + var writer = new Excel2TextWriter(); + + if (options.IsTransform) + { + if (options.Files.Count != 2) + { + Console.WriteLine("Usage: Excel2TextDiff -t "); + Environment.Exit(1); + } + + writer.TransformToTextAndSave(options.Files[0], options.Files[1]); + } + else + { + if (options.Files.Count != 2) + { + Console.WriteLine("Usage: Excel2TextDiff -d [-p ]"); + Environment.Exit(1); + } + + var diffProgame = options.DiffProgram ?? "TortoiseMerge.exe"; + + var tempTxt1 = Path.GetTempFileName(); + writer.TransformToTextAndSave(options.Files[0], tempTxt1); + + var tempTxt2 = Path.GetTempFileName(); + writer.TransformToTextAndSave(options.Files[1], tempTxt2); + + string arg1 = $"/base:{tempTxt1.Replace('\\', '/')}"; + string arg2 = $"/mine:{tempTxt2.Replace('\\', '/')}"; + Console.WriteLine(" {0} {1}", arg1, arg2); + System.Diagnostics.Process.Start(diffProgame, new string[] { arg1, arg2 }); + } + } + + private static CommandLineOptions ParseOptions(String[] args) + { + var helpWriter = new StringWriter(); + var parser = new Parser(ps => + { + ps.HelpWriter = helpWriter; + }); + + var result = parser.ParseArguments(args); + if (result.Tag == ParserResultType.NotParsed) + { + Console.Error.WriteLine(helpWriter.ToString()); + Environment.Exit(1); + } + return ((Parsed)result).Value; + } + } +} diff --git a/src/Luban.sln b/src/Luban.sln index d1ea460..2afa966 100644 --- a/src/Luban.sln +++ b/src/Luban.sln @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Job.Proto", "Luban.Jo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Job.Db", "Luban.Job.Db\Luban.Job.Db.csproj", "{7467AC15-C61F-4C56-942F-18EAEA902C58}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Excel2TextDiff", "Excel2TextDiff\Excel2TextDiff.csproj", "{9477226F-469E-458F-A3AD-9115D777A65A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +59,10 @@ Global {7467AC15-C61F-4C56-942F-18EAEA902C58}.Debug|Any CPU.Build.0 = Debug|Any CPU {7467AC15-C61F-4C56-942F-18EAEA902C58}.Release|Any CPU.ActiveCfg = Release|Any CPU {7467AC15-C61F-4C56-942F-18EAEA902C58}.Release|Any CPU.Build.0 = Release|Any CPU + {9477226F-469E-458F-A3AD-9115D777A65A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9477226F-469E-458F-A3AD-9115D777A65A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9477226F-469E-458F-A3AD-9115D777A65A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9477226F-469E-458F-A3AD-9115D777A65A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE