Rich 944868a0b4 Changed an Error Message to provide the location where the error occured.
Changed StepLevel property for Cautions and Notes to reduce the probability that notes or cautions will be split over a page break.
Added IsNumbered Property to aid in pagination.
2013-05-13 10:41:52 +00:00

1136 lines
40 KiB
C#
Raw Blame History

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Csla;
using Csla.Data;
using System.Data;
using System.Data.SqlClient;
//-----------------
using System.Drawing;
using System.Text.RegularExpressions;
using LBWordLibrary;
using System.Drawing.Imaging;
using Volian.Base.Library;
using System.Diagnostics;
namespace VEPROMS.CSLA.Library
{
public enum VolianStatusType
{
Initialize,
Update,
Complete
}
public delegate void VolianStatusChange(VolianStatusType type, int count, string text);
public partial class Document
{
public string DocumentTitle
{
get
{
if (_LibTitle == "") return string.Format("Document {0}", _DocID);
return _LibTitle;
}
}
public void UpdateDRoUsages(List<string> roids)
{
_DocumentDROUsageCount = -1;
if (DocumentDROUsages.Count > 0)
{
List<DocumentDROUsage> delList = new List<DocumentDROUsage>();
foreach (DocumentDROUsage myUsage in DocumentDROUsages)
{
string roidkey = string.Format("{0}:{1}", myUsage.RODbID, myUsage.ROID);
if (roids.Contains(roidkey))
roids.Remove(roidkey);// If in both, nothing to do
else
delList.Add(myUsage);
}
foreach (DocumentDROUsage myUsage in delList)
DocumentDROUsages.Remove(myUsage); // If only in old, remove it
}
foreach (string roidkey in roids)
{
string [] parts = roidkey.Split(":".ToCharArray());
DocumentDROUsages.Add(parts[1], RODb.GetJustRoDb(int.Parse(parts[0])));
}
}
/// <summary>
/// FixString processes the string returned and changes any symbols (0xF0??) to normal characters
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
//private static string FixString(string str)
//{
// StringBuilder results = new StringBuilder();
// foreach (char c in str)
// {
// if ((c & 0xFF00) == 0xF000)
// results.Append((char)(c & 0xFF));
// else
// results.Append((char)(c));
// }
// return results.ToString();
//}
}
public partial class DocumentInfo
{
public string DocumentTitle
{
get
{
if (_LibTitle == "") return string.Format("Document {0}", _DocID);
return _LibTitle;
}
}
public string LibraryDocumentUsage
{
get
{
StringBuilder sb = new StringBuilder();
string sep = "\r\nUsed In:\r\n ";
if (DocumentEntries == null)
sb.Append("None");
else
{
int limit = 20;
foreach (EntryInfo myEntry in DocumentEntries)
{
foreach (ItemInfo myItem in myEntry.MyContent.ContentItems)
{
--limit;
if (limit < 0)
{
sb.Append(sep + "...");
return sb.ToString();
}
ItemInfo proc = myItem.MyProcedure;
sb.Append(sep + proc.DisplayNumber + " - " + proc.DisplayText);
sep = "\r\n ";
}
}
}
return sb.ToString();
}
}
public ItemInfoList LibraryDocumentUsageList
{
get
{
bool first = true;
ItemInfoList iil = null;
if (DocumentEntries == null) return null;
foreach (EntryInfo myEntry in DocumentEntries)
{
foreach (ItemInfo myitem in myEntry.MyContent.ContentItems)
{
if (first)
{
iil = new ItemInfoList(myitem);
first = false;
}
else
iil.AddItem(myitem);
}
}
return iil;
}
}
#region DocumentConfig
[NonSerialized]
private DocumentConfig _DocumentConfig;
public DocumentConfig DocumentConfig
{ get { return (_DocumentConfig != null ? _DocumentConfig : _DocumentConfig = new DocumentConfig(this)); } }
public void RefreshConfig()
{
_DocumentConfig = null;
}
#endregion
public static DocumentInfo GetByLibDocName(string libdoc, int versionID)
{
try
{
DocumentInfo tmp = DataPortal.Fetch<DocumentInfo>(new LibDocCriteria(libdoc, versionID));
return tmp;
}
catch (Exception ex)
{
throw new DbCslaException("Error on DocumentInfo.GetByLibDocName", ex);
}
}
[Serializable()]
protected class LibDocCriteria
{
private string _LibDoc;
public string LibDoc
{ get { return _LibDoc; } }
private int _VersionID;
public int VersionID
{ get { return _VersionID; } }
public LibDocCriteria(string libdoc, int versionid)
{
_LibDoc = libdoc;
_VersionID = versionid;
}
}
private void DataPortal_Fetch(LibDocCriteria criteria)
{
if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] DocumentInfo.DataPortal_Fetch", GetHashCode());
try
{
using (SqlConnection cn = Database.VEPROMS_SqlConnection)
{
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "getDocumentByLibDoc";
cm.Parameters.AddWithValue("@LibDoc", criteria.LibDoc);
cm.Parameters.AddWithValue("@VersionID", criteria.VersionID);
cm.CommandTimeout = Database.DefaultTimeout;
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
if (!dr.Read())
{
_ErrorMessage = "No Record Found";
return;
}
ReadData(dr);
}
}
}
}
catch (Exception ex)
{
if (_MyLog.IsErrorEnabled) _MyLog.Error("DocumentInfo.DataPortal_Fetch", ex);
throw new DbCslaException("DocumentInfo.DataPortal_Fetch", ex);
}
}
}
public partial class DocumentInfoList
{
public static DocumentInfoList GetLibraries(bool forceload)
{
try
{
if (!forceload && _DocumentInfoList != null)
return _DocumentInfoList;
DocumentInfoList tmp = DataPortal.Fetch<DocumentInfoList>(new LibraryCriteria(true));
DocumentInfo.AddList(tmp);
tmp.AddEvents();
_DocumentInfoList = tmp;
return tmp;
}
catch (Exception ex)
{
throw new DbCslaException("Error on DocumentInfoList.Get", ex);
}
}
[Serializable()]
protected class LibraryCriteria
{
private bool _IsLibrary;
public bool IsLibrary
{
get { return _IsLibrary; }
set { _IsLibrary = value; }
}
public LibraryCriteria(bool islibrary)
{
_IsLibrary = islibrary;
}
}
private void DataPortal_Fetch(LibraryCriteria criteria)
{
this.RaiseListChangedEvents = false;
if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] DocumentInfoList.DataPortal_Fetch", GetHashCode());
try
{
using (SqlConnection cn = Database.VEPROMS_SqlConnection)
{
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "getLibraryDocuments";
cm.CommandTimeout = Database.DefaultTimeout;
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
IsReadOnly = false;
while (dr.Read()) this.Add(new DocumentInfo(dr));
IsReadOnly = true;
}
}
}
}
catch (Exception ex)
{
if (_MyLog.IsErrorEnabled) _MyLog.Error("DocumentInfoList.DataPortal_Fetch", ex);
throw new DbCslaException("DocumentInfoList.DataPortal_Fetch", ex);
}
this.RaiseListChangedEvents = true;
}
}
public class DSOFile : IDisposable
{
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#region Fields
private bool _IsDisposed;
private DocumentInfo _MyDocument = null;
private FileInfo _MyFile = null;
private string _Extension = "DOC";
#endregion
#region Properties
public DocumentInfo MyDocument
{
get { return _MyDocument; }
set
{
TryDelete();
_MyDocument = value;
CreateFile();
}
}
public FileInfo MyFile
{
get { return _MyFile; }
}
public string Extension
{
get { return _Extension; }
set { _Extension = value; }
}
#endregion
#region Private Methods
private void TryDelete()
{
if (_MyDocument == null) return;
if (_MyFile == null) return;
if (_MyFile.Exists)
{
try
{
_MyFile.Delete();
}
catch (IOException ex)
{
// _MyLog.Error("TryDelete", ex);
}
finally
{
_MyFile = null;
_MyDocument = null;
}
}
}
private bool _Created = false;
private int _Unique = 0;
private string Unique
{
get
{
string retval = "";
if (_Unique != 0) retval = "_" + _Unique.ToString();
_Unique++;
return retval;
}
}
private void CreateFile()
{
while (!_Created)
CreateTemporaryFile();
}
private void CreateTemporaryFile()
{
try
{
if (_MyDocument != null)
{
_MyFile = new FileInfo(string.Format(@"{0}\tmp_{1}{2}{3}", VlnSettings.TemporaryFolder, MyDocument.DocID, Unique, MyDocument.FileExtension));
while (_MyFile.Exists)
{
_MyFile = new FileInfo(string.Format(@"{0}\tmp_{1}{2}{3}", VlnSettings.TemporaryFolder, MyDocument.DocID, Unique, MyDocument.FileExtension));
}
FileStream fs = _MyFile.Create();
if (MyDocument.DocContent != null) fs.Write(MyDocument.DocContent, 0, MyDocument.DocContent.Length);
fs.Close();
_MyFile.CreationTimeUtc = _MyDocument.DTS;
_MyFile.LastWriteTimeUtc = _MyDocument.DTS;
_Created = true;
}
}
catch (Exception ex)
{
_MyLog.Error("***** Could not create " + _MyFile.FullName, ex);
Console.WriteLine(ex.Message);
}
}
public string FullName
{
get { return _MyFile.FullName; }
set
{
if (FullName != value)
_MyFile = new FileInfo(value);
}
}
public void SaveFile(float length, string ascii, ItemInfo myItemInfo, bool cvtLibDoc, VolianStatusChange statusChange)
{
// TODO: Add Try & Catch logic
if (_MyDocument == null) return;
Document doc = _MyDocument.Get();
FileStream fs = _MyFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Byte[] buf = new byte[_MyFile.Length];
fs.Read(buf, 0, buf.Length);
fs.Close();
// Handle if this is a libdoc & the user wanted to convert to a non-library document.
if (cvtLibDoc)
{
// if just one usage (this one), then just convert this to a non-library document. If there is more
// than one usage, make a copy so that the rest of the usages still point to the library document.
if (doc.DocumentEntryCount == 1)
doc.LibTitle = null;
else
{
// make new document with 'no' libtitle. Then link this to the item/content via the entry.
// the data gets set below.
Document tdoc = Document.MakeDocument(null, null, null, null);
_MyDocument = DocumentInfo.Get(doc.DocID);
doc = tdoc;
using (Entry ent = myItemInfo.MyContent.MyEntry.Get())
{
ent.MyDocument = tdoc;
ent.Save();
}
}
}
doc.FileExtension = MyFile.Extension;
doc.DocContent = buf;
doc.DocAscii = ascii;
//doc.UpdateDocAscii(_MyFile.FullName);
DocumentConfig cfg = new DocumentConfig(doc);
cfg.Edit_Initialized = true;
doc.Config = cfg.ToString();
doc.UserID = Volian.Base.Library.VlnSettings.UserID;
doc.DTS = _MyFile.LastWriteTimeUtc;
doc = doc.Save();
List<string> roids = new List<string>();
string pdfTmp = MSWordToPDF.ToPDFReplaceROs(_MyDocument, roids, myItemInfo,statusChange);
FileInfo pdfFile = new FileInfo(pdfTmp);
fs = pdfFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
buf = new byte[pdfFile.Length];
fs.Read(buf, 0, buf.Length);
fs.Close();
pdfFile.Delete();
Pdf.DeleteAll(doc.DocID); // clear the PDF table for DocID first
DocStyle myDocStyle = myItemInfo.ActiveSection.MyDocStyle;
SectionConfig sc = myItemInfo.ActiveSection.MyConfig as SectionConfig;
if (sc != null && sc.Section_WordMargin == "Y")
{
using (Pdf myPdf = Pdf.MakePdf(doc, MSWordToPDF.DebugStatus, 0, 0, 0, 0, (double)myItemInfo.MSWordPageCount, buf)) { ;}
}
else
{
using (Pdf myPdf = Pdf.MakePdf(doc, MSWordToPDF.DebugStatus, (int)myDocStyle.Layout.TopMargin, (int)myDocStyle.Layout.PageLength,
(int)myDocStyle.Layout.LeftMargin, (int)myDocStyle.Layout.PageWidth, (double)myItemInfo.MSWordPageCount, buf)) { ;}
}
doc.UpdateDRoUsages(roids);
doc.Save();
}
#endregion
#region Constructors
public DSOFile(DocumentInfo myDocument)
{
MyDocument = myDocument;
}
#endregion
#region Destructor
~DSOFile()
{
Dispose(false);
}
public void Dispose()
{
Dispose(false);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (!_IsDisposed)
{
_IsDisposed = true;
TryDelete();
}
}
#endregion
}
public static class MSWordToPDF
{
private static bool _CloseWordWhenDone = true;
public static bool CloseWordWhenDone
{
get { return MSWordToPDF._CloseWordWhenDone; }
set { MSWordToPDF._CloseWordWhenDone = value; }
}
private static LBApplicationClass _MyApp = null;
public static LBApplicationClass MyApp
{
get
{
if (_MyApp == null)
_MyApp = new LBApplicationClass();
return _MyApp;
}
}
private static int _DebugStatus = 0;
public static int DebugStatus
{
get { return MSWordToPDF._DebugStatus; }
set { MSWordToPDF._DebugStatus = value; }
}
private static System.Drawing.Color _OverrideColor = System.Drawing.Color.Transparent;
public static System.Drawing.Color OverrideColor
{
get { return MSWordToPDF._OverrideColor; }
set { MSWordToPDF._OverrideColor = value; }
}
private static System.Windows.Forms.Form _FormForPlotGraphics=null;
public static System.Windows.Forms.Form FormForPlotGraphics
{
get { return MSWordToPDF._FormForPlotGraphics; }
set { MSWordToPDF._FormForPlotGraphics = value; }
}
private static SectionInfo _MySection;
public static string GetDocPdf(SectionInfo sect, Color overrideColor)
{
_MySection = sect;
DocumentInfo mydoc = sect.MyContent.MyEntry.MyDocument;
UpdateDocPdf(mydoc, overrideColor,sect);
string fileName = GetFileName(sect);
FileInfo fi = new FileInfo(fileName);
FileStream fs = fi.Create();
PdfInfo myPdf = PdfInfo.Get(sect);
if (myPdf != null && myPdf.DocPdf != null) fs.Write(myPdf.DocPdf, 0, myPdf.DocPdf.Length);
fs.Close();
return fileName;
}
public static bool UpdateDocPdf(DocumentInfo mydoc, Color overrideColor, ItemInfo sect)
{
MSWordToPDF.OverrideColor = overrideColor;
PdfInfo myPdf = PdfInfo.Get(sect);
return true;
}
public static bool SetDocPdf(DocumentInfo docInfo, ItemInfo sect)
{
string pdfTmp = null;
List<string> roids = new List<string>();
try
{
pdfTmp = MSWordToPDF.ToPDFReplaceROs(docInfo,roids,sect,null);
}
catch (Exception ex)
{
return false;
}
if (pdfTmp == null) return false;
FileInfo pdfFile = new FileInfo(pdfTmp);
FileStream fs = pdfFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Byte[] buf = new byte[pdfFile.Length];
fs.Read(buf, 0, buf.Length);
fs.Close();
pdfFile.Delete();
using (Document doc = docInfo.Get())
{
DocStyle myDocStyle = sect.ActiveSection.MyDocStyle;
SectionConfig sc = sect.ActiveSection.MyConfig as SectionConfig;
if (sc != null && sc.Section_WordMargin == "Y")
{
using (Pdf myPdf = Pdf.MakePdf(doc, MSWordToPDF.DebugStatus, 0, 0, 0, 0, (double)sect.MSWordPageCount, buf)) { ;}
}
else
{
using (Pdf myPdf1 = Pdf.MakePdf(doc, MSWordToPDF.DebugStatus, (int)myDocStyle.Layout.TopMargin, (int)myDocStyle.Layout.PageLength,
(int)myDocStyle.Layout.LeftMargin, (int)myDocStyle.Layout.PageWidth, (double)sect.MSWordPageCount, buf)) { ;}
}
doc.UpdateDRoUsages(roids);
doc.Save();
}
docInfo.RefreshConfig();
return true;
}
public static string ToPDFReplaceROs(DocumentInfo doc, List<string> roids, ItemInfo sect, VolianStatusChange statusChange)
{
//ItemInfo sect = doc.DocumentEntries[0].MyContent.ContentItems[0];
return ToPDFReplaceROs(sect, false, roids, statusChange);
}
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static string ToPDFReplaceROs(ItemInfo sect, bool openPdf, List<string> roids, VolianStatusChange statusChange) //, System.Drawing.Color overrideColor, System.Windows.Forms.Form myForm)
{
string fileName = GetFileName(sect);
// TODO: do we want to cache the word pdfs
//if (System.IO.File.Exists(@"C:\Temp\" + fileName + ".pdf"))
// return @"C:\Temp\" + fileName + ".pdf";
//int docStyleIndex = ((int)sect.MyContent.Type) % 10000;
//DocStyle myDocStyle = sect.ActiveFormat.PlantFormat.DocStyles.DocStyleList[docStyleIndex];
DocStyle myDocStyle = sect.MyDocStyle;
//PageStyle myPageStyle = myDocStyle.pagestyle;
ProcedureInfo proc = sect.MyProcedure;
DocVersionInfo dvi = proc.ActiveParent as DocVersionInfo;
bool hasRos = false;
ROFstInfo rofst = null;
ROFSTLookup lookup = null;
string igPrefix = null;
string spPrefix = null;
if (dvi.DocVersionAssociationCount > 0)
{
hasRos = true;
rofst = dvi.DocVersionAssociations[0].MyROFst;
lookup = rofst.ROFSTLookup;
igPrefix = dvi.DocVersionConfig.RODefaults_graphicsprefix;
spPrefix = dvi.DocVersionConfig.RODefaults_setpointprefix;
}
// string AccPageID = string.Format("<{0}-{1}>", accPrefix, roch.appid);
using (DSOFile myFile = new DSOFile(sect.MyContent.MyEntry.MyDocument))
{
// Increase the priority of the Word Process so that the pdf creation happens quickly
Process[] myProcessess = Process.GetProcessesByName("winword");
foreach (Process myProcess in myProcessess)
{
try
{
if (myProcess.PriorityClass != ProcessPriorityClass.High && myProcess.MainWindowTitle == "")
myProcess.PriorityClass = ProcessPriorityClass.High;
}
catch (Exception ex)
{
while (ex != null)
{
Console.WriteLine("{0} - {1}", ex.GetType().Name, ex.Message);
ex = ex.InnerException;
}
}
}
LBDocumentClass myDoc = MyApp.Documents.Open(myFile.FullName, false);
try
{
SectionConfig sc = sect.ActiveSection.MyConfig as SectionConfig;
if (sc == null || sc.Section_WordMargin == "N")
{
AdjustMargins(myDocStyle, myDoc, true);
}
}
catch (Exception ex)
{
_MyLog.Error("Could not Adjust Margins", ex);
}
LBSelection selxy = hasRos ? FindXyPlot() : null;
string pngFile = VlnSettings.TemporaryFolder + @"\XYPlot1.png"; //@"C:\Temp\XYPlot1.png";
if (File.Exists(pngFile)) File.Delete(pngFile);
int filecount = 1;
while (selxy != null)
{
string xyplot = selxy.Text;
xyplot = xyplot.Replace("`", "\xB0");
// The 16bit code must have kept the carriage returns in the word doc, if there
// are carriage returns in the plot language. Count number of carriage return/newlines
// so that they can be added back.
int cnt = 0;
int indxCr = xyplot.IndexOf("\r");
while (indxCr > 0)
{
cnt++;
indxCr = xyplot.IndexOf("\r", indxCr + 1);
}
// Setting the selected text to "" actually sets it to "\r", thus cnt-- (subtract one
// from cnt since there's already a return in the string.
cnt--;
float x = (float)selxy.get_Information(LBWdInformation.wdHorizontalPositionRelativeToPage);
float y = (float)selxy.get_Information(LBWdInformation.wdVerticalPositionRelativeToPage);
LBRange myRange = selxy.Paragraphs.First.Range;
float yTop = (float)myRange.get_Information(LBWdInformation.wdVerticalPositionRelativeToPage);
float yTop1 = (float)myRange.get_Information(LBWdInformation.wdVerticalPositionRelativeToTextBoundary);
selxy.Text = "";
if (cnt>0)for (int icnt = 0; icnt < cnt; icnt++) selxy.Text = selxy.Text + "\r";
pngFile = VlnSettings.TemporaryFolder + @"\XYPlot" + filecount.ToString() + @".png"; //@"C:\Temp\XYPlot1.png";
filecount++;
RectangleF plotRect = CreatePlot(pngFile, xyplot, 600F, FormForPlotGraphics);
float xAdjust = (float)-sect.MyDocStyle.Layout.LeftMargin;
float yAdjust = selxy.Font.Size;
LBShape shape = myDoc.Shapes.AddPicture(pngFile, x + xAdjust + plotRect.X, yAdjust + y - yTop + plotRect.Y, selxy.Range);
File.Delete(pngFile);
shape.LockAspectRatio = LBMsoTriState.msoTrue;
shape.Width = plotRect.Width;
selxy.WholeStory();
selxy = FindXyPlot();
}
LBSelection sel = MyApp.Selection;
sel.WholeStory();
if(statusChange != null) statusChange(VolianStatusType.Initialize, sel.End, "Refreshing ROs");
sel = hasRos ? FindRO() : null;
int roCount = 0;
while (sel != null)
{
if (statusChange != null) statusChange(VolianStatusType.Update, sel.Start, string.Format("{0} ROs Refreshed", ++roCount));
string val = lookup.GetROValueByAccPagID(sel.Text, spPrefix, igPrefix);
int? type = lookup.GetROTypeByAccPagID(sel.Text, spPrefix, igPrefix);
// if type is null, then set type to zero so that InsertROValue will put in "RO Not Found" for the value
if (type == null)
type = 0;
// If multiple return values includes X-Y Plot, check to see if it is an X-Y Plot
if ((type & 4) == 4 && val.StartsWith("<<G"))
type = 4;
string roid = lookup.GetROIDByAccPagID(sel.Text, spPrefix, igPrefix);
if (roid != null)
{
string roidkey = string.Format("{0}:{1}", rofst.RODbID, roid);
if (!roids.Contains(roidkey))
roids.Add(roidkey);
}
if ((int)type == 8) // Image
{
//Console.WriteLine("Image: {0} - {1}", sect.MyContent.Number, sect.MyContent.Text);
bool imageROTokenReplaced = false;
string[] vals = val.Split("\n".ToCharArray());
ROImageInfo roImage = ROImageInfo.GetByROFstID_FileName(rofst.ROFstID, vals[0]);
if (roImage != null)
{
ROImageFile roImageFile = new ROImageFile(roImage);
float width = 72 * Int32.Parse(vals[3], System.Globalization.NumberStyles.AllowHexSpecifier) / 12.0F;
int lines = Int32.Parse(vals[2], System.Globalization.NumberStyles.AllowHexSpecifier);
float height = 72 * lines / 6.0F;
float x = (float)sel.get_Information(LBWdInformation.wdHorizontalPositionRelativeToTextBoundary);
// 9.25 is the approximate offset of the base line of the font, i.e. doesn't include descender.
float y = (float)sel.get_Information(LBWdInformation.wdVerticalPositionRelativeToTextBoundary) + ((sel.Font.Size * 9.25F) / 12);
sel.Text = "";
LBShape shape = myDoc.Shapes.AddPicture(roImageFile.MyFile.FullName, x, y, sel.Range);
shape.RelativeVerticalPosition = LBWdRelativeVerticalPosition.wdRelativeVerticalPositionMargin;
shape.Top = y; // Reset value after setting flag RelativeVerticalPosition
shape.RelativeHorizontalPosition = LBWdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin;
shape.Left = x;
shape.Width = width;
shape.Height = height;
imageROTokenReplaced = true;
}
if (!imageROTokenReplaced)
sel.Text = string.Format("Bad Image Link (Missing Image File:{0})", vals[0]);
}
else if ((int)type == 4) // X-Y Plot
{
try
{
val = val.Replace("`", "\xB0");
// An X/Y Plot RO type might have text preceding the Plot Commands
int pstart = val.IndexOf("<<G"); // find the starting Plot Command
AddPrecedingText(sel, val.Substring(0, pstart));// replace the RO token with what's in front of the X/Y Plot
val = val.Substring(pstart); // set val to the start of the plot commands
//float width = 72 * Int32.Parse(vals[3], System.Globalization.NumberStyles.AllowHexSpecifier) / 12.0F;
//float height = 72 * lines / 6.0F;
pngFile = VlnSettings.TemporaryFolder + @"\XYPlot1.png"; //@"C:\Temp\XYPlot1.png";
RectangleF plotRect = CreatePlot(pngFile, val, 600F, FormForPlotGraphics);
//LBShape shape = myDoc.Shapes.AddPicture(@"C:\Temp\XYPlot.png", 0, 0, sel.Range);
float x = (float)sel.get_Information(LBWdInformation.wdHorizontalPositionRelativeToPage);
float y = (float)sel.get_Information(LBWdInformation.wdVerticalPositionRelativeToPage);
// if there is regular text before the plot, then count the number of lines
// and adjust the y position accordingly
int idx = sel.Text.IndexOf("\r");
while ((idx > 0) && (idx < sel.Text.Length + 1))
{
idx = sel.Text.IndexOf("\r", idx + 1);
y += (float)sel.ParagraphFormat.LineSpacing; // get_Information(LBWdLineSpacing.wdLineSpaceSingle);
}
//LBInlineShape shape = sel.InlineShapes.AddPicture(pngFile);
LBRange myRange = sel.Paragraphs.First.Range;
float yTop = (float)myRange.get_Information(LBWdInformation.wdVerticalPositionRelativeToPage);
float yTop1 = (float)myRange.get_Information(LBWdInformation.wdVerticalPositionRelativeToTextBoundary);
float xAdjust = (float)-sect.MyDocStyle.Layout.LeftMargin;
float yAdjust = sel.Font.Size;
// The following two lines made the xyplot location for WCN2 match the 16bit output. However, how the
// xTweak value is determined is phantom of Rich's mind. Word document location of the RO token
// will be modified in data before delivery so that this xTweak is not needed.
//float xTweak = -(30 + xAdjust) / 3; // Used to align plots for WCN2.
//LBShape shape = myDoc.Shapes.AddPicture(pngFile, x + xAdjust + plotRect.X + xTweak, yAdjust + y - yTop + plotRect.Y, sel.Range);
LBShape shape = myDoc.Shapes.AddPicture(pngFile, x + xAdjust + plotRect.X, yAdjust + y - yTop + plotRect.Y, sel.Range);
File.Delete(pngFile);
shape.LockAspectRatio = LBMsoTriState.msoTrue;
//shape.Width = .89F * shape.Width;
//shape.Width = float.Parse(tbAdjust.Text) * shape.Width;
shape.Width = plotRect.Width;
//shape.Height = .89F * shape.Height;
sel.WholeStory();
// TODO: Do we want to color code ROs
//sel.Range.Font.Color = LBWdColor.wdColorRed;
//shape.Width = width;
//shape.Height = height;
//imageROTokenReplaced = true;
}
catch (Exception ex)
{
// something is wrong with the X/Y plot RO.
// print out the un-processed X/Y plot RO value
sel.Text = val;
//return null;
}
}
else
{
if (val != null)
val = val.Replace("`", "\xB0");
//AddInfo("\tRO Found {0} = '{1}'", sel.Text, val);
// if val is null, then InsertROValue will put in "RO Not Found" for the value
InsertROValue(sel, val, sect.ActiveFormat.PlantFormat.FormatData.ROData.UpRoIfPrevUpper);
}
sel = FindRO();
}
if (statusChange != null) statusChange(VolianStatusType.Update, 0, "Creating PDF");
sel = MyApp.Selection;
sel.WholeStory();
//sel.Range.Font.Color = (LBWdColor)WordColor(PrintOverride.OverrideTextColor(System.Drawing.Color.Black));
sel.Range.Font.Color = (LBWdColor)WordColor(OverrideColor == System.Drawing.Color.Transparent ? System.Drawing.Color.Black : OverrideColor);
sect.MSWordPageCount = myDoc.Length;
// force Print of MS Word Attachment to Final without revisions and comments
myDoc.ActiveWindow.View.ShowRevisionsAndComments = false;
myDoc.ActiveWindow.View.RevisionsView = LBWdRevisionsView.wdRevisionsViewFinal;
fileName = CreatePDF(fileName, openPdf);
MyApp.ActiveDocument.Close(false);
if (CloseWordWhenDone)
{
CloseAppAfterWait();
}
if (statusChange != null) statusChange(VolianStatusType.Complete, 0, "");
return fileName;
}
}
public static void AddPrecedingText(LBSelection sel, string val)
{
if (val.IndexOf("_") == -1) // Is some of the text underlined?
{
sel.Text = val; // nothing is underlined, use text as is
return;
}
// Back in the DOS days, an underbar was used to toggle underlining on/off
// Spit the val text on the underbar characters
string[] parts = val.Split("_".ToCharArray());
foreach (string part in parts)
{
// If there is a carrage return, and underline is turned on, then turn off the underline
if (sel.Font.Underline != LBWdUnderline.wdUnderlineNone && part.Contains("\r"))
{
int idx = part.IndexOf("\r");
string part1 = part.Substring(0, idx);
string part2 = part.Substring(idx);
sel.TypeText(part1);
sel.Font.Underline = LBWdUnderline.wdUnderlineNone;
sel.TypeText(part2);
}
else // put out each part of the split text and toggle the underline on/off
{
sel.TypeText(part);
if (sel.Font.Underline == LBWdUnderline.wdUnderlineNone)
sel.Font.Underline = LBWdUnderline.wdUnderlineSingle;
else
sel.Font.Underline = LBWdUnderline.wdUnderlineNone;
}
}
// We are done processing the text in val, if underline is on, turn it off
if (sel.Font.Underline != LBWdUnderline.wdUnderlineNone)
sel.Font.Underline = LBWdUnderline.wdUnderlineNone;
}
public static void AdjustMargins(DocStyle myDocStyle, LBDocumentClass myDoc, bool printingMode)
{
float newTop = (float)myDocStyle.Layout.TopMargin;
float newLeft = (float)myDocStyle.Layout.LeftMargin;
float newLength = (float)myDocStyle.Layout.PageLength;
float newWidth = (float)myDocStyle.Layout.PageWidth;
float oldTop = myDoc.PageSetup.TopMargin;
float oldLeft = myDoc.PageSetup.LeftMargin;
float oldBottom = myDoc.PageSetup.BottomMargin;
float oldRight = myDoc.PageSetup.RightMargin;
float oldHeight = myDoc.PageSetup.PageHeight;
float oldWidth = myDoc.PageSetup.PageWidth;
// in the following line, the 2 accounts for a difference between how word treats margin versus
// ours, we are not exactly sure why.
float newRight = Math.Max(0, oldWidth - (newWidth + 2));
float newBottom = Math.Max(0, oldHeight - (newLength + newTop + 1));
//Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", newTop, newLeft, newLength, newWidth, oldTop, oldLeft, oldBottom, oldRight,oldHeight,oldWidth);
if (printingMode)
{
if (myDoc.PageSetup.BottomMargin != 9999999)
{
// the + 1 in the next line allows for rounding.
myDoc.PageSetup.BottomMargin = newBottom;
myDoc.PageSetup.RightMargin = newRight;
myDoc.PageSetup.LeftMargin = newLeft;
myDoc.PageSetup.TopMargin = newTop;
}
else
{
try
{
// the + 1 in the next line allows for rounding.
myDoc.PageSetup.BottomMargin = newBottom;
myDoc.PageSetup.RightMargin = newRight;
myDoc.PageSetup.LeftMargin = newLeft;
myDoc.PageSetup.TopMargin = newTop;
}
catch (Exception ex)
{
if (_MySection != null)
{
_MyLog.ErrorFormat("<<< ERROR >>> MSWord could not set margins\r\n==>'MSWord could not set margins',{0},'{1}','{2}'"
, _MySection.ItemID, _MySection.MyDocVersion.MyFolder.Name, _MySection.ShortPath);
}
else
_MyLog.Error("Could not set margins", ex);
}
}
}
else
{
myDoc.PageSetup.TopMargin = 0;
myDoc.PageSetup.LeftMargin = 0;
myDoc.PageSetup.RightMargin = (8.5F * 72) - newWidth + newLeft;
// For OHLP, docstyle (ohlpdoc.in) in 16-bit for "Cover Page", pagelen seems to be incorrect. It would
// put out text on a second page. The following code is to catch this condition and reset the bottom margin.
// 11 * 72 -> 11 inches converted to points. newLength is printable part so BottomMargin is unprintable part
if (newTop + 36 > ((11 * 72) - newLength)) // 36 is 1/2 inch
myDoc.PageSetup.BottomMargin = newTop + 36; // makes an 1/2 inch bottom margin
else
myDoc.PageSetup.BottomMargin = (11 * 72) - newLength;
}
}
public static void CloseApp()
{
//WaitMS(900);// This was added because MSWord will sometimes get the error below
// Microsoft Office Word has stopped working
// It appears that this is caused by quiting the MS Word application
// to soon after closing the document or doing an export.
MyApp.Quit(false);
_MyApp = null;
}
/// <summary>
/// This closes the MS Word Application, but, delays for about 1 second.
/// It appears that closing MSWord to quickly causes a:
/// "Microsoft Office Word has stopped working" error.
/// </summary>
public static void CloseAppAfterWait()
{
System.Windows.Forms.Application.DoEvents();
new CloseWordApp(_MyApp, 1000);
_MyApp = null;
}
private class CloseWordApp:System.Windows.Forms.Timer
{
LBApplicationClass _MyApp;
public LBApplicationClass MyApp
{
get { return _MyApp; }
set { _MyApp = value; }
}
public CloseWordApp(LBApplicationClass myApp, int interval)
{
MyApp = myApp;
Interval = interval;
Tick += new EventHandler(CloseWordApp_Tick);
Enabled = true;
}
void CloseWordApp_Tick(object sender, EventArgs e)
{
Enabled = false;
MyApp.Quit(false);
Dispose();
}
}
private static void WaitMS(int n)
{
DateTime dtw = DateTime.Now.AddMilliseconds(n);
while (DateTime.Now < dtw)
{
System.Windows.Forms.Application.DoEvents();
}
}
private static int WordColor(System.Drawing.Color color)
{
System.Drawing.Color c1 = System.Drawing.Color.FromArgb(0, color.B, color.G, color.R);
return c1.ToArgb();
}
private static string GetFileName(ItemInfo sect)
{
string fileName = VlnSettings.TemporaryFolder + @"\Doc " + sect.MyContent.MyEntry.DocID.ToString(); // +" " + (sect.DisplayNumber == "" ? sect.DisplayText : sect.DisplayNumber);
return fileName;
}
private static RectangleF CreatePlot(string pngFile, string xyPlot, float resolution, System.Windows.Forms.Form myForm)
{
RectangleF retval = new RectangleF(0, 0, 0, 0);
//Form frm = Application.OpenForms[0];
System.Windows.Forms.Form frm = myForm;
Graphics grfx = frm.CreateGraphics();
string emfFile = pngFile.Replace(".png", ".emf");
Metafile mf = new Metafile(emfFile, grfx.GetHdc());
grfx.Dispose();
grfx = Graphics.FromImage(mf);
float dpi = grfx.DpiX;
//grfx.ScaleTransform(resolution / grfx.DpiX, (resolution +1F) / grfx.DpiY);
grfx.ScaleTransform(resolution / grfx.DpiX, resolution / grfx.DpiY);
grfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
grfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
grfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
grfx.Clear(System.Drawing.Color.Transparent);
XYPlots.XYPlot.BlackColor = MSWordToPDF.OverrideColor == Color.Red ? Color.Red : Color.Black;
XYPlots.XYPlot myPlot = new XYPlots.XYPlot(xyPlot);
myPlot.SetMargins(0, 0, 0, 0);
myPlot.Process(new VG.VGOut_Graphics(grfx));
grfx.Dispose();
GraphicsUnit gu = new GraphicsUnit();
retval = mf.GetBounds(ref gu);
retval.Width *= dpi / resolution;
retval.Height *= dpi / resolution;
retval.X *= dpi / resolution;
retval.Y *= dpi / resolution;
//retval.X = myPlot.Width-retval.Width;
//AddInfo("{0},{1},{2},{3},{4},{5}", myPlot.Width, myPlot.Height, retval.Width, retval.Height,retval.X,retval.Y);
//Console.Write("{0},{1},{2},{3}", myPlot.Width, myPlot.Height, retval.Width, retval.Height);
mf.Save(pngFile, ImageFormat.Png);
//Console.WriteLine("'pngfile','{0}'", pngFile);
mf.Dispose();
FileInfo myFile = new System.IO.FileInfo(emfFile);
myFile.Delete();
return retval;
}
private static void InsertROValue(LBSelection sel, string roValue, bool upRoIfPrevUpper)
{
if (roValue == null)
{
sel.Text = "RO Not Found";
sel.Font.Color = LBWdColor.wdColorRed;
}
else
{
if (upRoIfPrevUpper && sel.LastWasUpper) roValue = roValue.ToUpper();
// Convert fortran formatted numbers to scientific notation.
//string tmp = DisplayRO.ConvertFortranFormatToScienctificNotation(roValue);
string tmp = ROFSTLookup.ConvertFortranFormatToScienctificNotation(roValue);
// Only in Word sections, convert the # to superscripts and ~ to subscrtipts
tmp = Regex.Replace(tmp, "[#](.*?)[#]", "\\up2 $1\\up0 ");// DOS Superscript
tmp = Regex.Replace(tmp, "[~](.*?)[~]", "\\dn2 $1\\up0 ");// DOS Subscript
tmp = tmp.Replace(@"\u160?", "\xA0");
tmp = tmp.Replace(@"\U160?", "\xA0");
tmp = tmp.Replace(@"[xB3]", "\xB3");
// Look for superscript or subscript and insert the appropriate commands
Match roMatch = Regex.Match(tmp, @"(.*?)\\(up2|dn2) (.*?)\\(up0|dn0) ");
if (roMatch.Groups.Count == 5)// Superscript or subscript found
{
sel.Font.Color = LBWdColor.wdColorRed;
while (roMatch.Groups.Count == 5)
{
sel.TypeText(roMatch.Groups[1].Value); // output the text preceeding the super or sub command
sel.Font.Position = roMatch.Groups[2].Value == "up2" ? 2 : -2; // Shift the vertical position for super or sub
sel.TypeText(roMatch.Groups[3].Value); // output the superscript or subscript
sel.Font.Position = 0; // restore the vertical position
tmp = tmp.Substring(roMatch.Length); // remove the processed text
roMatch = Regex.Match(tmp, @"(.*?)\\(up2|dn2) (.*?)\\(up0|dn0) "); // check to see if the text contain another super or sub
}
if (tmp != "")// Add any remaining text
sel.TypeText(tmp);
sel.Font.Color = LBWdColor.wdColorAutomatic;
}
else // if no superscripts or subscripts just output the text
{
roValue = roValue.Replace(@"\u160?", "\xA0");
roValue = roValue.Replace(@"\U160?", "\xA0");
roValue = roValue.Replace(@"[xB3]", "\xB3");
roValue = roValue.Replace(@"[XB3]", "\xB3");
sel.Text = roValue;
sel.Font.Color = LBWdColor.wdColorRed;
}
}
}
private static LBSelection FindXyPlot()
{
LBSelection sel = MyApp.Selection;
LBFind find = sel.Find;
find.ClearFormatting();
// Search string format - this is MSWord wildcard format
// If you do a search in MSWord, make sure wildcard box is checked and then press the
// Special button to see the definitions of the various wildcards
// [<] - Less-Than Character
// [!<> ]@ - 1 or more characters not including Less-Than, Greater-Than or Space
// - Dash
// [!<> ]@ - 1 or more characters not including Less-Than, Greater-Than or Space
// [>] - Greater-Than Character
find.Text = "[<][<]*[>][>]";
//find.Wrap = LBWdFindWrap.wdFindStop;
find.Wrap = LBWdFindWrap.wdFindContinue;
find.MatchCase = false;
find.MatchWholeWord = false;
find.MatchWildcards = true;
find.MatchSoundsLike = false;
find.MatchAllWordForms = false;
if (find.Execute()) return sel;
return null;
}
private static LBSelection FindRO()
{
int firstStart = 0;
bool executeResult = false;
LBSelection sel = null;
while (!executeResult)
{
sel = MyApp.Selection;
LBFind find = sel.Find;
find.ClearFormatting();
// Search string format - this is MSWord wildcard format
// If you do a search in MSWord, make sure wildcard box is checked and then press the
// Special button to see the definitions of the various wildcards
// [<] - Less-Than Character
// [!<> ]@ - 1 or more characters not including Less-Than, Greater-Than or Space
// - Dash
// [!<> ]@ - 1 or more characters not including Less-Than, Greater-Than or Space
// [>] - Greater-Than Character
find.Text = "[<][!<> ]@-[!<> ]@[>]";
find.Wrap = LBWdFindWrap.wdFindContinue;
find.MatchCase = false;
find.MatchWholeWord = false;
find.MatchWildcards = true;
find.MatchSoundsLike = false;
find.MatchAllWordForms = false;
executeResult = find.Execute();
if (!executeResult) return null;
// MS Word found 'invalid' ro when text had "[335.0<T<335.6<EFBFBD>C]" (not sure what problem was).
// When this occurred, the selection was found, but it's end = 0, so move 1 char past it.
// Also, need to simulate a loop by saving first position and if loop back to first position,
// we are done with the search.
if (sel.End == 0)
{
if (firstStart == sel.Start) return null;
if (firstStart == 0)
firstStart = sel.Start;
sel.MoveStart(LBWdUnits.wdCharacter, 1);
executeResult = false;
}
}
if (executeResult) return sel;
return null;
}
private static string CreatePDF(string fileName, bool openPdf)
{
//return MyApp.CreatePDF(@"C:\Temp\" + fileName + ".pdf", openPdf);
//return MyApp.CreatePDF(VlnSettings.TemporaryFolder + "\\" + fileName + ".pdf", openPdf);
return MyApp.CreatePDF(fileName + ".pdf", openPdf);
}
}
}