921 lines
37 KiB
C#
921 lines
37 KiB
C#
//using Microsoft.Office.Interop.Word;
|
||
using System.Drawing;
|
||
using UtilLib;
|
||
using System.Collections.Generic;
|
||
using System;
|
||
using Newtonsoft.Json;
|
||
using Microsoft.Office.Interop.Word;
|
||
using Microsoft.Office.Tools.Word;
|
||
using Bookmark = Microsoft.Office.Tools.Word.Bookmark;
|
||
using Section = Microsoft.Office.Interop.Word.Section;
|
||
using WdColor = Microsoft.Office.Interop.Word.WdColor;
|
||
using NPOI.XSSF.UserModel;
|
||
using System.Windows.Forms;
|
||
using NPOI.SS.UserModel;
|
||
using System.IO;
|
||
using AIProofread.Model;
|
||
using NPOI.SS.Util;
|
||
using NPOI.HSSF.Util;
|
||
using AIProofread.core;
|
||
|
||
namespace AIProofread
|
||
{
|
||
public class DocumentUtil
|
||
{
|
||
static int markId = 0;
|
||
|
||
/// <summary>
|
||
/// 添加一个书签
|
||
/// </summary>
|
||
/// <param name="color"></param>
|
||
/// <param name="start"></param>
|
||
/// <param name="end"></param>
|
||
/// <returns></returns>
|
||
public static Bookmark AddBookmark(string color, int start, int end)
|
||
{
|
||
var doc = Globals.ThisAddIn.Application.ActiveDocument;
|
||
var maxOffset = doc.Range().End;
|
||
if (start > maxOffset || end > maxOffset)
|
||
{
|
||
return null;
|
||
}
|
||
var document = Globals.Factory.GetVstoObject(doc);
|
||
var r = document.Range(start, end);
|
||
var mark = document.Controls.AddBookmark(r, string.Format("ai_mark_{0}", markId++));
|
||
mark.Tag = "ai_proofread";
|
||
if (color != null)
|
||
{
|
||
// 给选区添加背景颜色
|
||
r.Shading.BackgroundPatternColor = (WdColor)ColorTranslator.ToOle(Colors.FromHex(color));
|
||
}
|
||
|
||
return mark;
|
||
}
|
||
|
||
public static void SectionAddMark(string color)
|
||
{
|
||
|
||
|
||
var document = Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveDocument);
|
||
// 获取当前文档对象
|
||
var doc = Globals.ThisAddIn.Application.ActiveDocument;
|
||
// 获取选中
|
||
var sections = document.Sections;
|
||
|
||
foreach (Section section in sections)
|
||
{
|
||
var r = section.Range;
|
||
|
||
//Bookmark mark = r.Bookmarks.Add();
|
||
var mark = document.Controls.AddBookmark(r, string.Format("ai_mark_{0}", markId++));
|
||
mark.Tag = "ai_proofread";
|
||
// 给选区添加背景颜色
|
||
r.Shading.BackgroundPatternColor = (WdColor)ColorTranslator.ToOle(Colors.FromHex(color));
|
||
}
|
||
}
|
||
|
||
public static System.Collections.Generic.List<string> GetAllBookmark()
|
||
{
|
||
var bookmarks = Globals.ThisAddIn.Application.ActiveDocument.Bookmarks;
|
||
System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>();
|
||
foreach (Microsoft.Office.Interop.Word.Bookmark mark in bookmarks)
|
||
{
|
||
list.Add(mark.Name);
|
||
}
|
||
return list;
|
||
}
|
||
/// <summary>
|
||
/// 删除所有标签
|
||
/// </summary>
|
||
public static void RemoveBookmark()
|
||
{
|
||
RemoveBookmark(null);
|
||
}
|
||
|
||
public static void ClearProofreadMarks()
|
||
{
|
||
var document = Globals.ThisAddIn.Application.ActiveDocument;
|
||
var bookmarks = document.Bookmarks;
|
||
ControlCollection controls = Globals.Factory.GetVstoObject(document).Controls;
|
||
foreach (Microsoft.Office.Interop.Word.Bookmark mark in bookmarks)
|
||
{
|
||
if (Config.IsProofreadMark(mark.Name))
|
||
{
|
||
// 去除高亮
|
||
mark.Range.Shading.BackgroundPatternColor = WdColor.wdColorAutomatic;
|
||
// 去除下划线
|
||
//mark.Range.Underline = WdUnderline.wdUnderlineNone;
|
||
try
|
||
{
|
||
// feat(20250305): 清除批注的时候,如果监测到书签位置是空格,把空格给删了吧(无缓冲记录时)
|
||
string text = mark.Range.Text;
|
||
if (text != null && text.Trim().Length == 0)
|
||
{
|
||
mark.Range.Text = "";
|
||
}
|
||
mark.Delete();
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
LogHelper.Log("remove mark", e);
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
/// <summary>
|
||
/// 删除标签
|
||
/// </summary>
|
||
/// <param name="markId"></param>
|
||
public static void RemoveBookmark(string markId)
|
||
{
|
||
var document = Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveDocument);
|
||
if (document.Bookmarks.Count == 0) return;
|
||
// 不存在要移除的标签
|
||
if (null != markId && !document.Bookmarks.Exists(markId)) return;
|
||
var bookmarks = Globals.ThisAddIn.Application.ActiveDocument.Bookmarks;
|
||
foreach (Microsoft.Office.Interop.Word.Bookmark mark in bookmarks)
|
||
{
|
||
if (mark.Name == markId)
|
||
{
|
||
mark.Range.Shading.BackgroundPatternColor = (WdColor)WdColorIndex.wdAuto;
|
||
mark.Delete();
|
||
}
|
||
}
|
||
//foreach (var mark in document.Bookmarks)
|
||
//{
|
||
// if (markId != null)
|
||
// {
|
||
// if (mark.Name == markId)
|
||
// {
|
||
// // 删除
|
||
// mark.Delete();
|
||
// mark.Range.Shading.BackgroundPatternColor = (WdColor)WdColorIndex.wdAuto;
|
||
// return;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// mark.Delete();
|
||
// }
|
||
//}
|
||
}
|
||
|
||
public static System.Collections.Generic.List<string> GetSectionText()
|
||
{
|
||
var document = Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveDocument);
|
||
System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>();
|
||
if (document.Sections.Count == 0) return list;
|
||
foreach (Section item in document.Sections)
|
||
{
|
||
list.Add(item.Range.Text);
|
||
}
|
||
return list;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找偏移量
|
||
/// </summary>
|
||
private static readonly int INSERT_FIND_OFFSET = 5;
|
||
|
||
/// <summary>
|
||
/// 查找校对项对应的range
|
||
/// </summary>
|
||
/// <param name="correct">校对项</param>
|
||
/// <param name="sentense">当前校对项所在句子</param>
|
||
/// <param name="prevOffset">上一个校对项结束位置</param>
|
||
/// <param name="document"></param>
|
||
/// <param name="range"></param>
|
||
/// <returns></returns>
|
||
public static Range FindRange(CorrectItem correct, CorrectContext sentense, ref int prevOffset, Microsoft.Office.Interop.Word.Document document, Range range)
|
||
{
|
||
var paragraphText = range.Text;
|
||
|
||
string findText = correct.Origin;
|
||
int wordStart = correct.Start;
|
||
int wordEnd = correct.End;
|
||
|
||
int offset = sentense.SentenceOffset;
|
||
string originText = sentense.Insert;
|
||
|
||
object Start = range.Start + offset + wordStart;
|
||
object End = range.Start + offset + wordEnd;
|
||
|
||
try
|
||
{
|
||
var activeDocument = document;
|
||
// 查找对象位置
|
||
End = range.Start + offset + wordEnd;
|
||
Start = range.Start + offset + wordStart;
|
||
// 直接找到
|
||
var findRange = activeDocument.Range(ref Start, ref End);
|
||
// 判断对应选区是否是要找的文本
|
||
if (findRange.Text == findText)
|
||
{
|
||
return findRange;
|
||
}
|
||
#region 使用前后关联进行强匹配
|
||
// 找前缀
|
||
var prefix = wordStart > 2 ? (
|
||
wordStart > INSERT_FIND_OFFSET
|
||
? originText.Substring(wordStart - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET)
|
||
: originText.Substring(0, wordStart)
|
||
) : null;
|
||
// 找后缀
|
||
var suffix = prefix == null ? (
|
||
wordEnd + INSERT_FIND_OFFSET < originText.Length
|
||
? originText.Substring(wordStart, INSERT_FIND_OFFSET)
|
||
: originText.Substring(wordStart, originText.Length - wordStart)
|
||
) : null;
|
||
var start = prefix != null || suffix != null
|
||
? paragraphText.IndexOf(prefix ?? suffix, prevOffset) // item.start +
|
||
: -1;
|
||
|
||
if (start != -1)
|
||
{
|
||
var findOffset = range.Start + start + (prefix != null ? prefix.Length : 0);
|
||
findRange = document.Range(findOffset, findOffset + wordEnd - wordStart);
|
||
if (findRange.Text == findText) { return findRange; }
|
||
}
|
||
#endregion
|
||
|
||
// 使用段落字符串进行强匹配
|
||
start = paragraphText.IndexOf(findText, prevOffset);
|
||
if (start != -1)
|
||
{
|
||
start += range.Start;
|
||
return document.Range(start, start + findText.Length);
|
||
}
|
||
|
||
|
||
var msg1 = new Dictionary<string, object>{
|
||
{"message",range.Find.Found?"搜索到可用位置":"没有搜索到可用位置" },
|
||
{ "search_start",range.Start },
|
||
{ "search_end",range.End },
|
||
{ "search_text",range.Text }
|
||
};
|
||
LogHelper.Log(JsonConvert.SerializeObject(msg1));
|
||
//while (range.Find.Found)
|
||
//{
|
||
// var obj4 = range.Document;
|
||
// MatchControl = range.Start;
|
||
// MatchAlefHamza = range.End;
|
||
// var range2 = obj4.Range(ref MatchControl, ref MatchAlefHamza);
|
||
// num3 = range2.End;
|
||
// if (range2.Text == findText)
|
||
// {
|
||
// return range2;
|
||
// }
|
||
// break;
|
||
// //if (findIndex == num)
|
||
// //{
|
||
|
||
// //}
|
||
// //num++;
|
||
// //range.Find.MatchByte = true;
|
||
// //Find find2 = range.Find;
|
||
// //MatchAlefHamza = missword;
|
||
// //MatchControl = true;
|
||
// //MatchDiacritics = Type.Missing;
|
||
// //MatchKashida = Type.Missing;
|
||
// //Replace = Type.Missing;
|
||
// //ReplaceWith = Type.Missing;
|
||
// //Format = Type.Missing;
|
||
// //Wrap = Type.Missing;
|
||
// //Forward = Type.Missing;
|
||
// //MatchAllWordForms = Type.Missing;
|
||
// //MatchSoundsLike = Type.Missing;
|
||
// //MatchWildcards = Type.Missing;
|
||
// //MatchWholeWord = Type.Missing;
|
||
// //Start = Type.Missing;
|
||
// //End = Type.Missing;
|
||
// //// 再次重复查找
|
||
// //find2.Execute(ref MatchAlefHamza, ref MatchControl, ref MatchDiacritics, ref MatchKashida, ref Replace, ref ReplaceWith, ref Format, ref Wrap, ref Forward, ref MatchAllWordForms, ref MatchSoundsLike, ref MatchWildcards, ref MatchWholeWord, ref Start, ref End);
|
||
//}
|
||
//if (num3 == 0)
|
||
//{
|
||
// return null;
|
||
//}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log(ex);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
|
||
public static Bookmark FindBookMarkByCorrect(CorrectItem correct)
|
||
{
|
||
try
|
||
{
|
||
var document = Globals.ThisAddIn.ActiveDocument.CurrentDocument;
|
||
var marks = document.Bookmarks;
|
||
var markName = Config.BuildBookmarkName(correct.Id);
|
||
|
||
if (!document.Bookmarks.Exists(markName)) return null;
|
||
|
||
ControlCollection controls = Globals.Factory.GetVstoObject(document).Controls;
|
||
//return controls[markName] as Bookmark;
|
||
//var obj = controls[markName];
|
||
var bookmark = marks[markName];
|
||
var start = bookmark.Range.Start;
|
||
var end = bookmark.Range.End;
|
||
// 删除原有书签
|
||
controls.Remove(markName);
|
||
return controls.AddBookmark(document.Range(start, end), markName);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log(ex);
|
||
}
|
||
return null;
|
||
|
||
//if(bookmark == null)
|
||
//{
|
||
// foreach (var m in marks)
|
||
// {
|
||
// var mark = m as Bookmark;
|
||
// var name = mark.Name;
|
||
// var tag = mark.Tag?.ToString();
|
||
// if(tag == markName || name == markName)
|
||
// {
|
||
// return mark;
|
||
// }
|
||
// }
|
||
//}
|
||
//return bookmark as Bookmark;
|
||
}
|
||
|
||
public static Bookmark FindRangeAndCreateBookmark(CorrectItem correct, CorrectContext sentense, Microsoft.Office.Interop.Word.Document document, ref int prevOffset)
|
||
{
|
||
Bookmark bookmark = null;
|
||
try
|
||
{
|
||
ControlCollection controls = Globals.Factory.GetVstoObject(document).Controls;
|
||
var markName = Config.BuildBookmarkName(correct.Id);
|
||
|
||
// 判断是否已经存在
|
||
if (controls.Contains(markName))
|
||
{
|
||
try
|
||
{
|
||
controls.Remove(markName);
|
||
}
|
||
catch (Exception) { }
|
||
}
|
||
// 判断段落是否存在
|
||
if (sentense.ParagraphNumber > document.Paragraphs.Count) return null;
|
||
|
||
var paragraph = document.Paragraphs[sentense.ParagraphNumber];
|
||
|
||
var findRange = FindRangeByCorrect(sentense, correct, paragraph, document, prevOffset);
|
||
if (findRange != null)
|
||
{
|
||
// 更新查找的结束位置
|
||
//prevOffset = findRange.End - paragraphStart;
|
||
bookmark = controls.AddBookmark(findRange, markName);
|
||
|
||
bookmark.Tag = "ai_proofread";
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log("create mark error:" + ex.Message + "\n" + ex.StackTrace + "\n\n");
|
||
}
|
||
return bookmark;
|
||
}
|
||
|
||
private static Range FindBySentence(Range paraRange, CorrectContext c, CorrectItem item, Microsoft.Office.Interop.Word.Document document)
|
||
{
|
||
try
|
||
{
|
||
var allSentenceCount = paraRange.Sentences.Count;
|
||
if (allSentenceCount < c.SentenceNumber) return null;
|
||
var sentence = paraRange.Sentences[c.SentenceNumber]; //paraText.Substring(c.SentenceOffset, c.InsertLength);
|
||
c.SentenceOffset = sentence.Start;
|
||
var offset = c.SentenceOffset;
|
||
|
||
if (c.Insert.TrimEnd() == sentence.Text.TrimEnd())
|
||
{
|
||
if (item.Tag == "i")
|
||
{
|
||
return document.Range(offset + item.Start, offset + item.Start);
|
||
}
|
||
//int count = 0;
|
||
var range = document.Range(offset + item.Start, offset + item.End + 1);
|
||
//while (true && count++ < 10)
|
||
//{
|
||
// //
|
||
// try
|
||
// {
|
||
// if (range.Text == null && range.Comments.Count > 0)
|
||
// {
|
||
// // 删除批注
|
||
// foreach (Comment comment in range.Comments)
|
||
// {
|
||
// comment.Delete();
|
||
// }
|
||
// continue;
|
||
// }
|
||
// else
|
||
// {
|
||
// break;
|
||
// }
|
||
// }
|
||
// catch (Exception dce)
|
||
// {
|
||
// Logger.Log(dce);
|
||
// }
|
||
//}
|
||
// 比对原始内容与校对原文是否一致
|
||
if (range.Text == item.Origin)
|
||
{
|
||
return range;
|
||
}
|
||
}
|
||
// 直接找
|
||
var range1 = document.Range(offset + item.Start, offset + item.End + 1);
|
||
// 兼容空格的全角与半角
|
||
if (item.Origin == " " && (range1.Text == " " || range1.Text == " " || range1.Text.Trim().Length == 0))
|
||
{
|
||
return range1;
|
||
}
|
||
//
|
||
if (range1.Text == item.Origin)
|
||
{
|
||
return range1;
|
||
}
|
||
// 执行查找
|
||
return FindTextInRange(sentence, item.Origin);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
public static Range FindTextInRange(Range range, string searchText)
|
||
{
|
||
try
|
||
{
|
||
Find find = range.Find;
|
||
if (range.Comments.Count > 0)
|
||
{
|
||
// 当前区域有批注 执行忽略模式
|
||
find.MatchPhrase = true;
|
||
}
|
||
// 设置查找条件
|
||
find.Text = searchText;
|
||
find.Forward = true;
|
||
find.Wrap = WdFindWrap.wdFindContinue;
|
||
find.Execute();
|
||
if (find.Found) return range;
|
||
}
|
||
catch (Exception) { }
|
||
return null;
|
||
}
|
||
|
||
private static Range FindRangeByCorrect(CorrectContext c, CorrectItem item, Paragraph paragraph, Microsoft.Office.Interop.Word.Document document, int prevOffset)
|
||
{
|
||
|
||
var originText = c.Insert;
|
||
var paraRange = paragraph.Range;
|
||
var paraText = paraRange.Text;
|
||
var paraStart = paraRange.Start;
|
||
|
||
// 定位句子的其实位置
|
||
//var offset = paraStart + c.SentenceOffset;
|
||
////var cutLength = Math.Min(c.InsertLen, paraText.Length - offset);
|
||
|
||
var originFindRange = FindBySentence(paraRange, c, item, document);
|
||
if (originFindRange != null) return originFindRange;
|
||
|
||
// 如果是新增 则查找定位
|
||
if (item.Tag == "i")
|
||
{
|
||
// 找前缀
|
||
var prefix1 = item.Start > 2 ? (
|
||
item.Start > INSERT_FIND_OFFSET
|
||
? originText.Substring(item.Start - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET)
|
||
: originText.Substring(0, item.Start)
|
||
) : null;
|
||
// 找后缀
|
||
var suffix1 = prefix1 == null ? (
|
||
item.End + INSERT_FIND_OFFSET < originText.Length
|
||
? originText.Substring(item.Start, INSERT_FIND_OFFSET)
|
||
: originText.Substring(item.Start, originText.Length - item.Start)
|
||
) : null;
|
||
// 偏移量
|
||
var start1 = prefix1 != null || suffix1 != null
|
||
? paraText.IndexOf(prefix1 ?? suffix1, prevOffset)
|
||
: -1;
|
||
if (start1 != -1)
|
||
{
|
||
var findOffset = paraStart + start1 + (prefix1 != null ? prefix1.Length : 0);
|
||
return document.Range(findOffset, findOffset);
|
||
}
|
||
}
|
||
|
||
if (prevOffset >= paraText.Length)
|
||
{
|
||
// 查找位置已经超过了整段长度了
|
||
LogHelper.Log("prevOffset:" + prevOffset + " paraText.Length:" + paraText.Length);
|
||
return null;
|
||
}
|
||
// 执行查找
|
||
int wordStart = item.Start;
|
||
int wordEnd = item.End;
|
||
|
||
// 找前缀
|
||
var prefix = wordStart > 2 ? (
|
||
wordStart > INSERT_FIND_OFFSET
|
||
? originText.Substring(wordStart - INSERT_FIND_OFFSET, INSERT_FIND_OFFSET)
|
||
: originText.Substring(0, wordStart)
|
||
) : null;
|
||
|
||
// 找后缀
|
||
var suffix = prefix == null ? (
|
||
wordEnd + INSERT_FIND_OFFSET < originText.Length
|
||
? originText.Substring(wordStart, INSERT_FIND_OFFSET)
|
||
: originText.Substring(wordStart, originText.Length - wordStart)
|
||
) : null;
|
||
|
||
var start = prefix != null || suffix != null
|
||
? paraText.IndexOf(prefix ?? suffix, prevOffset) // item.start +
|
||
: -1;
|
||
if (start != -1)
|
||
{
|
||
var findOffset = paraRange.Start + start + (prefix != null ? prefix.Length : 0);
|
||
prevOffset = start;
|
||
var range = document.Range(findOffset, findOffset + wordEnd - wordStart + 1);
|
||
|
||
if (item.Origin == " " && (range.Text == " " || range.Text == " " || range.Text.Trim().Length == 0))
|
||
{
|
||
return range;
|
||
}
|
||
if (range.Text == item.Origin) { return range; }
|
||
}
|
||
// 使用find查找
|
||
var r = FindTextInRange(paraRange, item.Origin);
|
||
if (r != null)
|
||
{
|
||
// 判断找到的range是否和查找区域误差过大
|
||
return r;
|
||
}
|
||
// 直接定位查找
|
||
start = paraText.IndexOf(item.Origin, prevOffset);
|
||
if (start == -1) return null;
|
||
// 定位整体开始位置
|
||
start = paraStart + start;
|
||
return document.Range(start, start + item.Origin.Length);
|
||
}
|
||
|
||
|
||
public static void ExportProofreadResult(string modelType)
|
||
{
|
||
string currentName = Globals.ThisAddIn.Application.ActiveDocument.Name;
|
||
// 去掉文件名后缀
|
||
currentName = currentName.Substring(0, currentName.LastIndexOf("."));
|
||
SaveFileDialog sfd = new SaveFileDialog();
|
||
modelType = modelType == "full" ? "查全" : "查准";
|
||
// 设置默认文件名
|
||
sfd.FileName = currentName + $"_勘误表_优先{modelType}.xlsx";
|
||
sfd.Filter = "Excel文件|*.xlsx";
|
||
var result = sfd.ShowDialog();
|
||
// 如果用户取消选择,则返回
|
||
if (result == DialogResult.Cancel)
|
||
{
|
||
return;
|
||
}
|
||
try
|
||
{
|
||
if (File.Exists(sfd.FileName))
|
||
{
|
||
// 判断原始文件是否可以删除
|
||
if (File.GetAttributes(sfd.FileName).HasFlag(FileAttributes.ReadOnly))
|
||
{
|
||
Globals.ThisAddIn.ShowDialog("已经存在名勘误表文件,请更换名称或手动删除", null, null);
|
||
return;
|
||
}
|
||
// 删除文件 重新写入新数据避免出现未知不可控bug
|
||
File.Delete(sfd.FileName);
|
||
}
|
||
//ProcessExport(sfd.FileName);
|
||
CorrectResultExportor.GetInstance().ExportResult(sfd.FileName);
|
||
Globals.ThisAddIn.ActiveDocument?.ShowMessage("导出勘误表成功", 2000, false);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
LogHelper.Log(e);
|
||
Globals.ThisAddIn.ShowDialog("导出勘误表失败,请重试", null, null);
|
||
}
|
||
}
|
||
|
||
private static NPOI.SS.UserModel.ICell CreateCell(IRow row, int colIndex, IFont font, string text, ICellStyle style = null)
|
||
{
|
||
var cell = row.CreateCell(colIndex);
|
||
if (font != null)
|
||
{
|
||
var value = new XSSFRichTextString(text);
|
||
value.ApplyFont(font);
|
||
cell.SetCellValue(value);
|
||
}
|
||
else
|
||
{
|
||
cell.SetCellValue(text);
|
||
}
|
||
if (style != null)
|
||
{
|
||
cell.CellStyle = style;
|
||
|
||
}
|
||
else
|
||
{
|
||
cell.CellStyle.WrapText = true;
|
||
}
|
||
return cell;
|
||
}
|
||
private static int RGB(int red, int green, int blue)
|
||
{
|
||
return red + (green << 8) + (blue << 16);
|
||
}
|
||
|
||
|
||
private static void ProcessExport(string fileName)
|
||
{
|
||
using (var fs = File.Create(fileName))
|
||
{
|
||
var book = new XSSFWorkbook();
|
||
var sheet = book.CreateSheet("Sheet1");
|
||
#region 基础设置
|
||
var simHeiFont = CreateBaseFont(book, "黑体", 11);
|
||
simHeiFont.Color = NPOI.HSSF.Util.HSSFColor.Black.Index;
|
||
// 设置表格样式
|
||
var style = CreateBaseCellStyle(book);
|
||
style.FillPattern = FillPattern.NoFill; // SolidForeground
|
||
/* 系统与正文用不同字体区分(包括顶部栏、处理列、新增、删除等提示)勘误表系统字体为黑体,所有字号统一 */
|
||
style.SetFont(simHeiFont);
|
||
style.BorderBottom = NPOI.SS.UserModel.BorderStyle.None;
|
||
style.BorderTop = NPOI.SS.UserModel.BorderStyle.None;
|
||
style.BorderLeft = NPOI.SS.UserModel.BorderStyle.None;
|
||
style.BorderRight = NPOI.SS.UserModel.BorderStyle.None;
|
||
style.WrapText = true;
|
||
|
||
// 设置宽度
|
||
sheet.SetColumnWidth(0, 1); // 序号
|
||
sheet.SetColumnHidden(0, true); // 隐藏序号
|
||
sheet.SetColumnWidth(3, 80 * 256); // 详细信息
|
||
sheet.SetColumnWidth(4, 20 * 256); // 异常
|
||
sheet.SetColumnWidth(5, 20 * 256); // 建议
|
||
sheet.SetColumnWidth(6, 10 * 256); // 处理状态
|
||
|
||
string[] headerTitles =
|
||
{
|
||
"序号","页","行","详细信息","异常", "建议","处理状态"
|
||
};
|
||
|
||
// 设置表头筛选及冻结 2.0.5 2024-12-30修改
|
||
sheet.CreateFreezePane(0, 1, 0, 1);
|
||
sheet.SetAutoFilter(CellRangeAddress.ValueOf("A1:G1"));
|
||
|
||
// 设置表头为白色
|
||
var headerStyle = book.CreateCellStyle();
|
||
var headerFont = book.CreateFont();
|
||
headerFont.FontName = "黑体"; // 设置字体
|
||
headerFont.FontHeightInPoints = 11; // 字体大小
|
||
var themeColor = new XSSFColor(new byte[] { 214, 170, 105 }); // 首行背景色黑色,字体用主题金色
|
||
((XSSFFont)headerFont).SetColor(themeColor);
|
||
headerStyle.SetFont(headerFont); // 应用字体
|
||
|
||
// 设置背景颜色为黑色
|
||
headerStyle.FillForegroundColor = HSSFColor.Black.Index; // 设置前景色
|
||
headerStyle.FillPattern = FillPattern.SolidForeground; // 使用实心填充模式
|
||
|
||
// 对齐方式
|
||
headerStyle.VerticalAlignment = VerticalAlignment.Center; // 垂直居中
|
||
headerStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; // 水平居中
|
||
|
||
// 表头设置
|
||
var row = sheet.CreateRow(0);
|
||
row.Height = 40 * 20; // 首行加高
|
||
for (int i = 0; i < 7; i++)
|
||
{
|
||
sheet.SetDefaultColumnStyle(i, style);
|
||
var cell = CreateCell(row, i, headerFont, headerTitles[i], headerStyle);
|
||
}
|
||
|
||
var blackFont = CreateBaseFont(book, NPOI.HSSF.Util.HSSFColor.Black.Index);
|
||
var redFont = CreateBaseFont(book, NPOI.HSSF.Util.HSSFColor.Red.Index);
|
||
|
||
// 获取排序后的数据
|
||
var list = ExportDataItem.GetExportData(Globals.ThisAddIn.ActiveDocument.marks);
|
||
// 对 list 进行排序
|
||
int id = 1;
|
||
|
||
var wrapTextStyle = book.CreateCellStyle();
|
||
wrapTextStyle.WrapText = true;
|
||
wrapTextStyle.VerticalAlignment = VerticalAlignment.Center;
|
||
|
||
var alignCenterStyle = book.CreateCellStyle();
|
||
alignCenterStyle.VerticalAlignment = VerticalAlignment.Center;
|
||
alignCenterStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
|
||
#endregion
|
||
foreach (var item in list)
|
||
{
|
||
try
|
||
{
|
||
var it = item.Item;
|
||
row = sheet.CreateRow(id);
|
||
row.Height = -1;
|
||
row.CreateCell(0).SetCellValue(id);
|
||
// 页码
|
||
var pageCell = row.CreateCell(1);
|
||
pageCell.CellStyle = alignCenterStyle;
|
||
pageCell.SetCellValue(item.PageNumber);
|
||
// 行号
|
||
var lineCell = row.CreateCell(2);
|
||
lineCell.CellStyle = alignCenterStyle;
|
||
lineCell.SetCellValue(item.LineNumber);
|
||
|
||
#region 引用原文内容
|
||
string originSentence = item.OriginSentence.TrimEnd();
|
||
var startIndex = it.Tag == "i" || it.Start < originSentence.Length - 1 ? it.Start : originSentence.IndexOf(it.Origin);
|
||
|
||
XSSFRichTextString originText = new XSSFRichTextString(originSentence);
|
||
originText.ApplyFont(blackFont);
|
||
try
|
||
{
|
||
originText.ApplyFont(it.Start, it.Start + (it.Tag == "i" ? it.Text.Length : it.Origin.Length), redFont);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
LogHelper.Log(e);
|
||
}
|
||
|
||
var oriCell = row.CreateCell(3);
|
||
// 设置单元格内容自动换行
|
||
oriCell.CellStyle = wrapTextStyle;
|
||
oriCell.SetCellValue(originText);
|
||
#endregion
|
||
|
||
// 原始内容
|
||
|
||
var cellOrigin = row.CreateCell(4);
|
||
cellOrigin.CellStyle = wrapTextStyle;
|
||
cellOrigin.SetCellValue(it.Origin);
|
||
|
||
#region 建议
|
||
var suggest = it.Text;
|
||
|
||
var cellSuggest = row.CreateCell(5);
|
||
cellSuggest.CellStyle = wrapTextStyle;
|
||
if (it.Tag == "r")
|
||
{
|
||
string tag = "";
|
||
if (it.Type == "blacklist")
|
||
{
|
||
tag = "黑名单";
|
||
}
|
||
else
|
||
{
|
||
// TODO 后期优化
|
||
// 易错词 标点 不标识
|
||
if (it.Type == "confusion" || it.Type == "model" || it.Type == "other" || it.Type == "punctuation")
|
||
{
|
||
//row.CreateCell(5).SetCellValue(suggest);
|
||
}
|
||
else if (!string.IsNullOrEmpty(it.Type) && ExportConfig.ErrorTypeMap.ContainsKey(it.Type.ToLower()))
|
||
{
|
||
|
||
tag = $"【提示】{ExportConfig.ErrorTypeMap[it.Type.ToLower()]}";
|
||
}
|
||
else if (!string.IsNullOrEmpty(it.Addition) && it.Addition.Trim().Length > 0 && it.Addition != "提示")
|
||
{
|
||
tag = $"【提示】{it.Addition}";
|
||
}
|
||
}
|
||
if (string.IsNullOrEmpty(tag))
|
||
{
|
||
cellSuggest.SetCellValue(suggest);
|
||
}
|
||
else
|
||
{
|
||
XSSFRichTextString replaceText = new XSSFRichTextString(suggest + $" {tag}");
|
||
replaceText.ApplyFont(blackFont);
|
||
// 对查找内容引用红色
|
||
replaceText.ApplyFont(suggest.Length + 1, suggest.Length + 1 + tag.Length, simHeiFont);
|
||
cellSuggest.SetCellValue(replaceText);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
string tag = "";
|
||
startIndex = 0;
|
||
if (it.Type == "incorrect_expression")
|
||
{
|
||
tag = "表述有误";
|
||
}
|
||
else if (it.Type == "sensitive")
|
||
{
|
||
tag = "敏感词";
|
||
}
|
||
else if (it.Type == "blacklist" || it.Type == "blacklist_mask")
|
||
{
|
||
tag = "黑名单";
|
||
}
|
||
else if (it.Type == "fallen_officers")
|
||
{
|
||
tag = "落马官员";
|
||
}
|
||
else if (it.Tag == "i")
|
||
{
|
||
startIndex = it.Text.Length + 1;
|
||
tag = it.Text + " 新增";
|
||
}
|
||
else if (it.Tag == "d")
|
||
{
|
||
tag = "删除";
|
||
}
|
||
XSSFRichTextString suggestText = new XSSFRichTextString(tag);
|
||
suggestText.ApplyFont(blackFont);
|
||
if (tag.Length > 0)
|
||
{
|
||
// 对查找内容引用红色
|
||
suggestText.ApplyFont(startIndex, it.Tag == "i" ? startIndex + 2 : tag.Length, simHeiFont);
|
||
cellSuggest.SetCellValue(suggestText);
|
||
}
|
||
else
|
||
{
|
||
cellSuggest.SetCellValue(suggest);
|
||
}
|
||
}
|
||
#endregion
|
||
// 处理状态
|
||
var statusValue = new XSSFRichTextString(StatusText(it.IsAccept));
|
||
statusValue.ApplyFont(simHeiFont);
|
||
var cellStatus = row.CreateCell(6);
|
||
cellStatus.CellStyle = alignCenterStyle;
|
||
cellStatus.SetCellValue(statusValue);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.Log(ex);
|
||
}
|
||
id++;
|
||
}
|
||
|
||
// 保存到文件
|
||
book.Write(fs);
|
||
//Globals.ThisAddIn.ShowMessage("导出成功", 3000);
|
||
}
|
||
}
|
||
|
||
|
||
private static ICellStyle CreateBaseCellStyle(IWorkbook workbook)
|
||
{
|
||
var style = workbook.CreateCellStyle();
|
||
style.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
|
||
style.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
|
||
style.WrapText = true;
|
||
|
||
return style;
|
||
}
|
||
private static IFont CreateBaseFont(IWorkbook workbook, string name, int size)
|
||
{
|
||
// 宋体 11
|
||
var font = workbook.CreateFont();
|
||
font.FontName = name;
|
||
font.FontHeightInPoints = size;
|
||
|
||
return font;
|
||
}
|
||
private static IFont CreateBaseFont(IWorkbook workbook, short color = -1)
|
||
{
|
||
var font = CreateBaseFont(workbook, "宋体", 11);
|
||
if (color != -1)
|
||
{
|
||
font.Color = color;
|
||
}
|
||
|
||
return font;
|
||
}
|
||
|
||
private static string StatusText(int status)
|
||
{
|
||
if (status == AcceptStatus.Accept) return "已采纳";
|
||
else if (status == AcceptStatus.Review) return "已复核";
|
||
else if (status == AcceptStatus.Ignore) return "已忽略";
|
||
|
||
return "未处理";
|
||
}
|
||
|
||
private static string GetInsertContentByLength(int length)
|
||
{
|
||
return new String('˽', length);
|
||
}
|
||
}
|
||
}
|