249 lines
5.6 KiB
C#
249 lines
5.6 KiB
C#
using ICSharpCode.SharpZipLib.Zip;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Security;
|
|
using System.Text;
|
|
|
|
namespace HiImRay
|
|
{
|
|
public class Docxument
|
|
{
|
|
protected string Filename { get; set; }
|
|
|
|
public int CompressionLevel { get; set; } = 9;
|
|
public Dictionary<string, string> ReplacementWords = new Dictionary<string, string>();
|
|
public Dictionary<string, List<Dictionary<string, string>>> ReplacementParagraphs = new Dictionary<string, List<Dictionary<string, string>>>();
|
|
|
|
public Docxument()
|
|
{
|
|
}
|
|
|
|
public Docxument(string filename)
|
|
{
|
|
Load(filename);
|
|
}
|
|
|
|
public void Load(string filename)
|
|
{
|
|
this.Filename = filename;
|
|
}
|
|
|
|
public void Save(string saveFilename)
|
|
{
|
|
int size = 2048;
|
|
byte[] buffer = new byte[size];
|
|
int bufferSize = 0;
|
|
|
|
// read file
|
|
ZipEntry readEntry = null;
|
|
ZipInputStream readStream = new ZipInputStream(File.OpenRead(this.Filename));
|
|
|
|
// write file
|
|
ZipOutputStream writeStream = new ZipOutputStream(File.Create(saveFilename));
|
|
writeStream.SetLevel(this.CompressionLevel);
|
|
|
|
// loop
|
|
while (true)
|
|
{
|
|
readEntry = readStream.GetNextEntry();
|
|
if (readEntry == null)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (!readEntry.IsFile)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(readEntry.Name))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// change document
|
|
if (readEntry.Name.Equals("word/document.xml"))
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
buffer = new byte[size];
|
|
bufferSize = 0;
|
|
|
|
do
|
|
{
|
|
bufferSize = readStream.Read(buffer, 0, buffer.Length);
|
|
ms.Write(buffer, 0, bufferSize);
|
|
} while (bufferSize > 0);
|
|
|
|
ms.Position = 0;
|
|
|
|
StreamReader sr = new StreamReader(ms);
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(sr.ReadToEnd());
|
|
|
|
// make changes
|
|
sb = replaceTokens(sb, this.ReplacementWords);
|
|
sb = replaceParagraphs(sb, this.ReplacementParagraphs);
|
|
|
|
// make readable
|
|
MemoryStream ms2 = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
|
|
ms2.Position = 0;
|
|
|
|
// write new document xml
|
|
writeStream.PutNextEntry(new ZipEntry(readEntry.Name));
|
|
|
|
buffer = new byte[size];
|
|
bufferSize = 0;
|
|
|
|
do
|
|
{
|
|
bufferSize = ms2.Read(buffer, 0, buffer.Length);
|
|
writeStream.Write(buffer, 0, bufferSize);
|
|
} while (bufferSize > 0);
|
|
|
|
ms2.Close();
|
|
ms2.Dispose();
|
|
}
|
|
else
|
|
{
|
|
writeStream.PutNextEntry(new ZipEntry(readEntry.Name));
|
|
|
|
buffer = new byte[size];
|
|
bufferSize = 0;
|
|
|
|
do
|
|
{
|
|
bufferSize = readStream.Read(buffer, 0, buffer.Length);
|
|
writeStream.Write(buffer, 0, bufferSize);
|
|
} while (bufferSize > 0);
|
|
}
|
|
}
|
|
|
|
writeStream.Finish();
|
|
writeStream.Flush();
|
|
writeStream.Close();
|
|
writeStream.Dispose();
|
|
|
|
readStream.Close();
|
|
readStream.Dispose();
|
|
}
|
|
|
|
protected StringBuilder replaceTokens(StringBuilder sb, Dictionary<string, string> options)
|
|
{
|
|
foreach (KeyValuePair<string, string> item in options)
|
|
{
|
|
sb.Replace("{{" + item.Key + "}}", SecurityElement.Escape(item.Value));
|
|
}
|
|
|
|
return sb;
|
|
}
|
|
|
|
protected StringBuilder replaceParagraphs(StringBuilder sb, Dictionary<string, List<Dictionary<string, string>>> options)
|
|
{
|
|
foreach (KeyValuePair<string, List<Dictionary<string, string>>> item in options)
|
|
{
|
|
sb = replaceParagraph(sb, item);
|
|
}
|
|
|
|
return sb;
|
|
}
|
|
|
|
protected StringBuilder replaceParagraph(StringBuilder sb, KeyValuePair<string, List<Dictionary<string, string>>> options)
|
|
{
|
|
string paragraph = sb.ToString();
|
|
|
|
Tuple<int, int> outerCoord = getOuterParagraph(paragraph, "{{" + options.Key + "}}");
|
|
if (outerCoord != null)
|
|
{
|
|
sb.Remove(outerCoord.Item1, outerCoord.Item2);
|
|
|
|
Tuple<int, int> innerCoord = getInnerParagraph(paragraph.Substring(outerCoord.Item1, outerCoord.Item2), "{{" + options.Key + "}}");
|
|
string innerParagraph = paragraph.Substring((innerCoord.Item1 + outerCoord.Item1), innerCoord.Item2);
|
|
|
|
StringBuilder innerText = new StringBuilder();
|
|
foreach (Dictionary<string, string> row in options.Value)
|
|
{
|
|
StringBuilder sb2 = new StringBuilder();
|
|
sb2.Append(innerParagraph);
|
|
|
|
sb2 = replaceTokens(sb2, row);
|
|
|
|
innerText.Append(sb2.ToString());
|
|
}
|
|
|
|
sb.Insert(outerCoord.Item1, innerText.ToString());
|
|
}
|
|
|
|
return sb;
|
|
}
|
|
|
|
protected Tuple<int, int> getOuterParagraph(string fullText, string findTerm)
|
|
{
|
|
string headTerm = "<w:p ";
|
|
string tailTerm = "</w:p>";
|
|
|
|
int headIndex = fullText.IndexOf(findTerm);
|
|
if (headIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
int tailIndex = fullText.IndexOf(findTerm, (headIndex + findTerm.Length));
|
|
if (tailIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
headIndex = fullText.LastIndexOf(headTerm, headIndex);
|
|
if (headIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
tailIndex = fullText.IndexOf(tailTerm, (tailIndex + tailTerm.Length));
|
|
if (tailIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
tailIndex += tailTerm.Length;
|
|
|
|
return new Tuple<int, int>(headIndex, (tailIndex - headIndex));
|
|
}
|
|
|
|
protected Tuple<int, int> getInnerParagraph(string fullText, string findTerm)
|
|
{
|
|
string headTerm = "<w:p ";
|
|
string tailTerm = "</w:p>";
|
|
|
|
int headIndex = fullText.IndexOf(findTerm);
|
|
if (headIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
int tailIndex = fullText.IndexOf(findTerm, (headIndex + findTerm.Length));
|
|
if (tailIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
headIndex = fullText.IndexOf(tailTerm, headIndex);
|
|
if (headIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
headIndex += tailTerm.Length;
|
|
|
|
tailIndex = fullText.LastIndexOf(headTerm, tailIndex);
|
|
if (tailIndex < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new Tuple<int, int>(headIndex, (tailIndex - headIndex));
|
|
}
|
|
}
|
|
}
|