问题点:NPOI处理xlsx文档时,将\r写成了换行符。

实例:以下字符abc\rcde

如果直接复制到Excel 2016,显示结果如下(单元格设置为折行显示):

如果用NPOI写入Xlsx文档,显示结果如下(单元格设置为折行显示):

代码如下:

            string path = @"C: \Users\Desktop\test.xlsx";

            var book = new XSSFWorkbook();
var sheet = book.CreateSheet("test");
var row = sheet.GetRow() ?? sheet.CreateRow();
var cell = row.GetCell() ?? row.CreateCell(); cell.SetCellValue("abc\rcde"); using (var file = new FileStream(path, FileMode.Create, FileAccess.Write))
{
book.Write(file);
file.Close();
}

查看生成的Excel内部数据确实成了换行符:

原因

OOXML因为使用XML格式存储数据,所以XML中无法表示的字符需要转换为Unicode码存储,Excel打开时会自动将这些Unicode码转换为原来的字符显示。由于NPOI需要兼容以前版本Excel,而没有处理'\t'  '\n'  '\r'这几个字符。

NPOI源码:

        public static string ExcelEncodeString(string t)
{
StringWriter sw = new StringWriter();
//poi dose not add prefix _x005f before _x????_ char.
//if (Regex.IsMatch(t, "(_x[0-9A-F]{4,4}_)"))
//{
// Match match = Regex.Match(t, "(_x[0-9A-F]{4,4}_)");
// int indexAdd = 0;
// while (match.Success)
// {
// t = t.Insert(match.Index + indexAdd, "_x005F");
// indexAdd += 6;
// match = match.NextMatch();
// }
//}
for (int i = ; i < t.Length; i++)
{
if (t[i] <= 0x1f && t[i] != '\t' && t[i] != '\n' && t[i] != '\r') //Not Tab, CR or LF
{
//[0x00-0x0a]-[\r\n\t]
//poi replace those chars with ?
sw.Write('?');
//sw.Write("_x00{0}_", (t[i] < 0xa ? "0" : "") + ((int)t[i]).ToString("X"));
}
else if (t[i] == '\uFFFE')
{
sw.Write('?');
}
else
{
sw.Write(t[i]);
}
}
return sw.ToString();
}

对应方法

Unicode表里面需要处理的部分:

遍历所有字符,将001f内的字符都转换为Unicode。

字符转换为Unicode代码:

        private static string EncodeXmlUTF(string value)
{
var builder = new StringBuilder();
foreach (char c in value.ToCharArray())
{
if (c < )
{
builder.Append($"_x{(c < 16 ? "" : "")}{Convert.ToInt32(c):X}_");
}
else
{
builder.Append(c);
}
}
return builder.ToString();
}

NPOI的场合

读取端:由于NPOI已经做了转换处理,所有不需要特别的代码。

写入端:

cell.SetCellValue(EncodeXmlUTF(text));

设置多文本的特殊处理:因为NPOI里面需要用到字符串位置信息,所有在它处理之后替换原先字符为Unicode。

            var text = new XSSFRichTextString("abcefg\rhijklmn");
text.ApplyFont(commonFont.Index);
text.ApplyFont(, , green_font); foreach (var r in text.GetCTRst().r)
{
r.t = EncodeXmlUTF(r.t);
}

OpenXML的场合

需要在SharedStringTable中写入SharedStringItem:

shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new Text(EncodeXmlUTF(value))));

读取的时候同理需要将SharedStringItem.InnerText转码后的数据转换回来:

Unicode转换回来代码:

        static String UtfDecode(String value)
{
if (value == null) return null; StringBuilder buf = new StringBuilder();
MatchCollection mc = utfPtrn.Matches(value);
int idx = ;
for (int i = ; i < mc.Count;i++ )
{
int pos = mc[i].Index;
if (pos > idx)
{
buf.Append(value.Substring(idx, pos-idx));
} String code = mc[i].Groups[].Value;
int icode = Int32.Parse(code, System.Globalization.NumberStyles.AllowHexSpecifier);
buf.Append((char)icode); idx = mc[i].Index+mc[i].Length;
}
buf.Append(value.Substring(idx));
return buf.ToString();
}

OOXML中回车等特殊字符处理方法的更多相关文章

  1. mssql sqlserver 使用sql脚本剔除数据中的tab、空格、回车等特殊字符的方法分享

    摘要: 在sqlserver开发中,常常有同事反馈无法剔除空格,我们可以通过仔细检查发现,并不是空格字符,而是tab键,如下所示: 解决方法: 对于这些特殊字符的替换,我们需采用字符所对应的ascii ...

  2. JavaScript中url 传递参数(特殊字符)解决方法及转码解码的介绍

    有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了.下表中列出了一些URL特殊符号及编码   十六进制值 1. + URL 中+号表示空格 %2B 2. 空 ...

  3. 在php中防止SQL注入的方法

    摘要:我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最主要就是要配置php.ini中的内容,让我们执行 php能够更安全.整个PH ...

  4. 客户端向服务端传送特殊字符解决方法(检测到有潜在危险的 Request.Form 值)

    当客户端向服务端传输特殊字符时报错,错误信息如下图:

  5. SQL对like 操作中的特殊字符处理方法

    SQL对like 操作中的特殊字符处理方法:    SQL Server查询过程中,单引号 ' 是特殊字符,所以在查询的时候要转换成双单引号 '' .    在like操作还有以下特殊字符:下划线_, ...

  6. Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理

    Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理 >>>>>>>>>>>>>>>>& ...

  7. Python中防止sql注入的方法详解

    SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库.下面这篇文章主要给大家介绍了关于Python中 ...

  8. 转:Scanner中nextLine()方法和next()方法的区别

    原文地址:https://blog.csdn.net/hello_word2/article/details/54895106 总结:next() 读取第一个 空白符之前(不包括空白符)的内容,nex ...

  9. Maya中输出nuke脚本的方法

    因项目需要,三维部门跟踪组动画组都需要一个能够快速输出nuke预合成工程的脚本.脚本已经写完,源码不便于放出来,写一个大致思路吧. 我首先分析了nuke工程,内部包含了哪些节点,这些节点有哪些属性需要 ...

随机推荐

  1. 运营的Python指南 - Python 操作Excel

    这是一份写给运营人员的Python指南.本文主要讲述如何使用Python操作Excel.完成Excel的创建,查询和修改操作. 相关代码请参考 https://github.com/RustFishe ...

  2. element 自定义 el-loading

    前言 虽说,el-loading 自带的loading效果已经满足日常的需求看 但是,美术大大觉得太low  我要我设计的,我不要你觉得我要我觉得 需求 自定义el-loading 正文 从官方需求文 ...

  3. 学习笔记43_T4模板

    新建-文本模板(后缀为.tt) <#@ template debug="false" hostspecific="false"  language=&qu ...

  4. 水管局长数据加强版:lct,时光倒流,最小生成树,边化点

    Description: SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到 ...

  5. 从壹开始【NetCore3.0】 46 ║ 授权认证:自定义返回格式

    前言 哈喽大家好,马上就要年末了,距离新的一年,只有50天了,春节是75天. 在这个时节内,天气逐渐变凉,但是大家的心肯定很热吧,因为发生了两件大事: 1.双十一买买买,在这个让人激动又纠结的一天,大 ...

  6. 八、springboot 简单优雅的通过docker-compose 构建

    前言 这个项目有一段时间没有更新了,不过我可没有偷懒哟,是偷偷准备了一个大招,现在是时候展示啦哈哈. 我们今天要做的,就是将我们的项目通过docker-compose 构建成镜像运行.为什么要这样做呢 ...

  7. 使用Typescript重构axios(二十四)——防御XSRF攻击

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  8. Java高性能反射工具包ReflectASM

    ReflectASM 使用字节码生成的方式实现了更为高效的反射机制.执行时会生成一个存取类来 set/get 字段,访问方法或创建实例.一看到 ASM 就能领悟到 ReflectASM 会用字节码生成 ...

  9. Linux如何添加硬盘

    一.命令操作: df       #查看磁盘空间 fdisk     #分区/查看分区 mkfs      #格式化 df  -h(以人类易读) -m(以M为单位读取)            #查看硬 ...

  10. 关于laravel框架Model返回的值为stdClass对象转换两种方法

    一般情况下laravel模型层查询出来的数据是stdClass对象,无法直接当做数组进行视图展示,所以需要转换为数组格式. Model中查到的数据为  $data  ,对它进行转化,转化为数组. 第一 ...