• Word 中的公式解析和还原方式与说明


    Word 中的公式解析和还原方式与说明

    Word 中的公式解析和还原方式与说明

    首先我们知道doc(office 2003)是流,docx(> office 2007)是open xml格式

    我想跨平台解析wrod 里面的公式 docx(> office 2007),于是我发现公式有3种格式(可能>3种)

    新ms office公式(>=2007)(只有这种支持open xml解析)

    老ms office公式(<2007)

    wps公式

    于是我写下了 这一篇文章 把 word 解析为html 希望支持 文字,图片,公式(未实现),表格(未实现)

    https://www.cnblogs.com/ping9719/p/12462478.html (如果需要简单的解析为html的可以参考此文档)

    我并不想管其他2个公式,但是我发现有以下几个问题:

    1.公式解析是别人写的

    2.公式前端还需要额外的js库

    3.无法html转为word时还原公式,使用户可以在编辑(这个最重要)

    于是我在换思路:

    所以我这边建议使用 wps 或者 ms office 转为html+xml,这样子就支持了所有的公式和格式

    wps 支持跨平台(jsapi):

    https://code.aliyun.com/zouyingfeng/wps/tree/master

    https://zhuanlan.zhihu.com/c_1256350603921915904

    但是为了方便我没有使用wps+jsapi

    我使用为wps+vsto,他们的类库差不多的,可以有参考价值

    实现的思路为:

    代码实现:

    建立项目 net standard 2.0

    随便为了支持一下 net 4.5版本

    编辑   .csproj  文件

      <PropertyGroup>
    	  <TargetFrameworks>net45;netstandard20</TargetFrameworks>
      </PropertyGroup>
    

      

     引用COM:

     引用包对C#语言支持:

     我的项目结构为:

    这个结构方便我以后对ppt和excel的支持代码,同事支持wps+ms office

    下面开始:

    加入文件 OfficeApp.cs

        /// <summary>
        /// office应用
        /// </summary>
        public class OfficeApp
        {
            /// <summary>
            /// WPS 2019+窗体模式 是否为整合模式
            /// </summary>
            private bool? IsWpsFormMergeModel
            {
                get
                {
                    return null;
                }
            }
    
            /// <summary>
            /// 得到进程中的word应用
            /// </summary>
            /// <param name="appType">0没有找到 1 office 2 wps</param>
            /// <returns>word应用</returns>
            public static object GetProcessesWordApp(out OfficeType officeType)
            {
                officeType = OfficeType.Null;
    
                //MS Office
                if (Process.GetProcessesByName("WINWORD").Count() > 0)
                {
                    officeType = OfficeType.Microsoft;
                    return DllImportHelp.GetActiveObject("Word.Application");
                }
                else if (Process.GetProcessesByName("wps").Count() > 0)
                {
                    //WPS Office V9
                    if (Type.GetTypeFromProgID("KWPS.Application") != null)
                    {
                        officeType = OfficeType.WPS;
                        return DllImportHelp.GetActiveObject("KWPS.Application");
                    }
                    //WPS Office V8
                    else if (Type.GetTypeFromProgID("WPS.Application") != null)
                    {
                        officeType = OfficeType.WPS;
                        return DllImportHelp.GetActiveObject("WPS.Application");
                    }
                    else
                        return null;
                }
                else
                {
                    return null;
                }
            }
        }
    

    加入文件 RangeEx.cs

        public static class RangeEx
        {
            /// <summary>
            /// 统一设置颜色(文字,下划线,音调符号,表格边框)
            /// </summary>
            public static void SetColor(this Range range, WdColor wdColor)
            {
                range.Font.Color = wdColor;
                range.Font.DiacriticColor = wdColor;
                range.Font.UnderlineColor = wdColor;
                foreach (Table table in range.Tables)
                {
                    table.Borders.InsideColor = wdColor;
                    table.Borders.OutsideColor = wdColor;
                }
            }
    
            /// <summary>
            /// 是否无内容
            /// </summary>
            public static bool IsNull(this Range range)
            {
                //对公式等检测
                if (range.Text.Length == range.End - range.Start)
                {
                    //对图片等检测
                    string txt = range.Text.Replace("
    ", "").Replace("
    ", "").Replace("v", "");
                    if (string.IsNullOrEmpty(txt))
                        return true;
                }
                return false;
            }
    
            /// <summary>
            /// 是否无内容或者空格组成
            /// </summary>
            public static bool IsNullOrSpace(this Range range)
            {
                //对公式等检测
                if (range.Text.Length == range.End - range.Start)
                {
                    //对图片等检测
                    string txt = range.Text.Trim();
                    if (string.IsNullOrWhiteSpace(txt))
                        return true;
                }
                return false;
            }
    
            /// <summary>
            /// 替换
            /// </summary>
            /// <param name="range"></param>
            /// <param name="findText">查找内容</param>
            /// <param name="replacementText">替换内容</param>
            public static bool Replace(this Range range, string findText, string newValue)
            {
                Find find = range.Find;
                find.Replacement.ClearFormatting();
                find.Text = findText;
                find.Replacement.Text = newValue;
                find.Forward = false;
                find.Wrap = WdFindWrap.wdFindStop;
                find.Format = false;
                find.MatchCase = true;//区分大小写
                find.MatchWholeWord = false;
                find.MatchByte = true;
                find.MatchAllWordForms = false;
                find.MatchSoundsLike = false;
                find.MatchWildcards = false;
                find.MatchFuzzy = false;
    
                return find.Execute(MatchControl: WdReplace.wdReplaceAll);
            }
    
            /// <summary>
            /// 得到环绕模式为悬浮的表格
            /// </summary>
            /// <param name="range"></param>
            public static List<Table> GetFloatTable(this Range range)
            {
                if (range == null)
    
    //....................此文件十分重要,只贴部分代码......
    

      

    加入文件 DllImportHelp.cs

        public static class DllImportHelp
        {
            /// <summary>
            /// net core 没有GetActiveObject()方法 所以调用dll
            /// </summary>
            /// <param name="progId"></param>
            /// <returns></returns>
            public static object GetActiveObject(string progId)
            {
                if (progId == null)
                    return null;
    
                var hr = CLSIDFromProgIDEx(progId, out var clsid);
                if (hr < 0)
                    return null;
    
                hr = GetActiveObject(clsid, IntPtr.Zero, out var obj);
                if (hr < 0)
                    return null;
                return obj;
            }
    
            [DllImport("ole32")]
            private static extern int CLSIDFromProgIDEx([MarshalAs(UnmanagedType.LPWStr)] string lpszProgID, out Guid lpclsid);
    
            [DllImport("oleaut32")]
            private static extern int GetActiveObject([MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pvReserved, [MarshalAs(UnmanagedType.IUnknown)] out object ppunk);
        }
    

      

        /// <summary>
        /// office程序类型
        /// </summary>
        public enum OfficeType
        {
            /// <summary>
            /// 为空的
            /// </summary>
            Null,
            /// <summary>
            /// WPS Office
            /// </summary>
            WPS,
            /// <summary>
            /// Microsoft Office
            /// </summary>
            Microsoft,
            /// <summary>
            /// 未知的程序
            /// </summary>
            Unknown,
        }
    

      

    加入文件 WordApp.cs

    /// <summary>
        /// Word应用
        /// </summary>
        public class WordApp
        {
            /// <summary>
            /// 查找符:软回车,同html中的br
            /// </summary>
            public const string Find_BlankRow = "^l";
            /// <summary>
            /// 查找符:段落
            /// </summary>
            public const string Find_Paragraph = "^p";
            /// <summary>
            /// 查找符:段落 通配符
            /// </summary>
            public const string Find_ParagraphASCII = "^13";
    
            private OfficeType _AppType = OfficeType.Null;
            /// <summary>
            /// Office类型
            /// </summary>
            public OfficeType AppType
            {
                get
                {
                    if (_AppType != OfficeType.Null)
                        return _AppType;
    
                    if (File.Exists(App.Path + "/wps.exe") || File.Exists(App.Path + "wpsoffice.exe"))
                        _AppType = OfficeType.WPS;
                    else if (File.Exists(App.Path + "/MSOHTMED.EXE") || File.Exists(App.Path + "MSQRY32.EXE"))
                        _AppType = OfficeType.Microsoft;
                    else
                        _AppType = OfficeType.Unknown;
    
                    return _AppType;
                }
                private set { _AppType = value; }
            }
    
            /// <summary>
            /// 整个应用程序
            /// </summary>
            public Application App { get; private set; }
    
            /// <summary>
            /// 活动中(正在操作)的Word文档
            /// </summary>
            public Document Doc { get; private set; }
    
            /// <summary>
            /// 是否存在文件路径
            /// </summary>
            public bool IsExistFilePath { get => Doc.FullName.Contains(':'); }
    
            ///// <summary>
            ///// 初始化程序和活动中的word (vsto)
            ///// </summary>
            //public WordApp()
            //{
            //    App = Globals.ThisAddIn.Application;
            //    try
            //    {
            //        Doc = App.ActiveDocument;
            //    }
            //    catch { }
            //}
    
            /// <summary>
            /// 初始化word程序
            /// </summary>
            public WordApp()
            {
                var wordObj = OfficeApp.GetProcessesWordApp(out OfficeType officeType);
                if (wordObj == null)
                    App = new Application();
                else
                {
                    App = (Application)wordObj;
                    AppType = officeType;
                }
    
                Doc = App.Documents.Add();
            }
    
            /// <summary>
            /// 初始化word程序
            /// </summary>
            public WordApp(string fileName)
            {
                var wordObj = OfficeApp.GetProcessesWordApp(out OfficeType officeType);
                if (wordObj == null)
                    App = new Application();
                else
                {
                    App = (Application)wordObj;
                    AppType = officeType;
                }
    
                Doc = App.Documents.Open(fileName);
            }
    
            /// <summary>
            /// 初始化程序,需要有活动中的word
            /// </summary>
            public WordApp(Application app)
            {
                App = app;
    
                try
                {
                    Doc = app.ActiveDocument;
                }
                catch { }
            }
    
            /// <summary>
            /// 初始化word程序
            /// </summary>
            public WordApp(Document doc)
            {
                if (doc != null)
                {
                    App = doc.Application;
                    Doc = doc;
                }
            }
    
            /// <summary>
            /// 全新的文档
            /// </summary>
            public void NewDoc()
            {
                Close();
                Doc = App.Documents.Add();
            }
    
            /// <summary>
            /// 得到文档的数量
            /// </summary>
            public int GetDocCount()
            {
                if (App == null)
                    return 0;
                return App.Documents.Count;
            }
    
            /// <summary>
            /// 替换(WPS 有些情况有bug)
            /// </summary>
            /// <param name="findText">查找内容</param>
            /// <param name="newValue">替换内容</param>
            public bool Replace(string findText, string newValue)
            {
                return RangeEx.Replace(Doc.Content, findText, newValue);
            }
    //....................此文件十分重要,只贴部分代码......

    --------------------------------------------------

    -----------------------------------------------

    -----------------------

    -----------

    ---  

    开始(最重要的代码)

    //导出
    
    //全文
    new WordApp().Doc.Content.ExportFragment(@"D:123.html", WdSaveFormat.wdFormatHTML);
    //部分,段落,公式...
    Range.ExportFragment(@"D:123.html", WdSaveFormat.wdFormatHTML);
    
    //全文
    new WordApp().Doc.Content.ExportFragment(@"D:123.xml", WdSaveFormat.wdFormatXMLDocument);
    //部分,段落,公式...
    Range.ExportFragment(@"D:123.xml", WdSaveFormat.wdFormatXMLDocument);
    

     html里面有很多无用的标签,需要自己清除

    //还原
    
    Range.InsertFile(@"D:123.html");
    
    Range.InsertFile(@"D:123.xml");
    

      

    部署到IIS的问题:

    1.需要安装。net core 对应版本的运行时(自己百度)

    2.需要给iis管理员权限(https://blog.csdn.net/q646926099/article/details/52421273

     ok,...

  • 相关阅读:
    LoadRunner参数化&关联
    面试题
    Python---Pycharm如何直接上传自己的代码到GitHub
    深入详解美团点评CAT跨语言服务监控(九)CAT管理平台MVC框架
    深入详解美团点评CAT跨语言服务监控(八)报表持久化
    深入详解美团点评CAT跨语言服务监控(七)消息分析器与报表(二)
    深入详解美团点评CAT跨语言服务监控(六)消息分析器与报表(一)
    深入详解美团点评CAT跨语言服务监控(五)配置与数据库操作
    深入详解美团点评CAT跨语言服务监控(四)服务端消息分发
    深入详解美团点评CAT跨语言服务监控(三)CAT客户端原理
  • 原文地址:https://www.cnblogs.com/ping9719/p/14151162.html
Copyright © 2020-2023  润新知