hiimray-co-uk-www-posts/2019/02/Docxument.cs

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 (string.IsNullOrWhiteSpace(readEntry.Name))
{
break;
}
if (!readEntry.IsFile)
{
continue;
}
// 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));
}
}
}