OOXML中回车等特殊字符处理方法
问题点: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中回车等特殊字符处理方法的更多相关文章
- mssql sqlserver 使用sql脚本剔除数据中的tab、空格、回车等特殊字符的方法分享
摘要: 在sqlserver开发中,常常有同事反馈无法剔除空格,我们可以通过仔细检查发现,并不是空格字符,而是tab键,如下所示: 解决方法: 对于这些特殊字符的替换,我们需采用字符所对应的ascii ...
- JavaScript中url 传递参数(特殊字符)解决方法及转码解码的介绍
有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了.下表中列出了一些URL特殊符号及编码 十六进制值 1. + URL 中+号表示空格 %2B 2. 空 ...
- 在php中防止SQL注入的方法
摘要:我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最主要就是要配置php.ini中的内容,让我们执行 php能够更安全.整个PH ...
- 客户端向服务端传送特殊字符解决方法(检测到有潜在危险的 Request.Form 值)
当客户端向服务端传输特殊字符时报错,错误信息如下图:
- SQL对like 操作中的特殊字符处理方法
SQL对like 操作中的特殊字符处理方法: SQL Server查询过程中,单引号 ' 是特殊字符,所以在查询的时候要转换成双单引号 '' . 在like操作还有以下特殊字符:下划线_, ...
- Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理
Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理 >>>>>>>>>>>>>>>>& ...
- Python中防止sql注入的方法详解
SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库.下面这篇文章主要给大家介绍了关于Python中 ...
- 转:Scanner中nextLine()方法和next()方法的区别
原文地址:https://blog.csdn.net/hello_word2/article/details/54895106 总结:next() 读取第一个 空白符之前(不包括空白符)的内容,nex ...
- Maya中输出nuke脚本的方法
因项目需要,三维部门跟踪组动画组都需要一个能够快速输出nuke预合成工程的脚本.脚本已经写完,源码不便于放出来,写一个大致思路吧. 我首先分析了nuke工程,内部包含了哪些节点,这些节点有哪些属性需要 ...
随机推荐
- Nexus安装(Windows)
1. nexus下载 官网下载:https://www.sonatype.com/download-oss-sonatype 网盘下载:https://pan.baidu.com/s/1CXOW7Lv ...
- (Java) Md5Utils
package com.vcgeek.hephaestus.utils; import java.security.MessageDigest; public class Md5Utils { /** ...
- [2018-01-12] laravel--路由(路由与控制器)
路由只用来接收请求 目前我们大致了解了laravel,在开始一个Http程序需要先定义路由.之前的例子中,我们的业务逻辑都是在路由里实现的,这对于简单的网站或web应用没什么问题,当我们需要扩大规模, ...
- Java零基础入门之常用工具
Java异常 什么是异常? 在程序运行过程中,意外发生的情况,背离我们程序本身的意图的表现,都可以理解为异常. throwable是所有异常的根类,异常分为两种异常exception和error Er ...
- 深度学习tensorflow实战笔记 用预训练好的VGG-16模型提取图像特征
1.首先就要下载模型结构 首先要做的就是下载训练好的模型结构和预训练好的模型,结构地址是:点击打开链接 模型结构如下: 文件test_vgg16.py可以用于提取特征.其中vgg16.npy是需要单独 ...
- 【Elasticsearch 7 探索之路】(二)文档的 CRUD 和批量操作
上一篇,我们介绍了什么是 Elasticsearch,它能做什么用以及基本概念(索引 Index.文档 Document.类型 Type)理解.这篇主要对 文档的基本 CRUD 和 倒排索引进行讲解. ...
- 品优购(IDEA版)-第二天
品优购-第2天 学习目标 目标1:运用AngularJS前端框架的常用指令 目标2:完成品牌管理的列表功能 目标3:完成品牌管理的分页列表功能 目标4:完成品牌管理的增加功能 目标5:完成品牌管理的修 ...
- html5不能播放视频的方法
html5不能播放视频的方法H5不能播放视频的方法 格式工厂转换成 AVC 注意音频流 采样率和比特率 设置低一点 不然播放会卡住 还有点击播放必须要click 不要用touchstart没效果的
- jquery手机端横屏判断方法
jquery手机端横屏判断方法<pre>$(function() { var bodywidth = $('body').width(); var bodyheight = $('body ...
- python基础-匿名函数和内置函数
匿名函数和内置函数 匿名函数:没有名字,使用一次即被收回,加括号就可以运行的函数. 语法:lambda 参数:返回值 使用方式: 将匿名函数赋值给变量,给匿名函数一个名字,使用这个变量来调用(还不如用 ...