Development #117

Merged
djankowski merged 5 commits from Development into master 2023-09-14 15:58:52 -04:00
8 changed files with 335 additions and 0 deletions

Binary file not shown.

View File

@ -160,6 +160,107 @@ namespace VEPROMS.CSLA.Library
}
}
}
// B2023-093 This method is called before editing or printing a Word section and will convert it the Word .DOCX format if needed.
// Note that the core logic was taken from frmSectionProperties.cs and modified to convert both .RTF and .DOC files
// The conversion to DOCX is needs to be done only one time per Word section
public static void ConvertWordSectionToDOCX(ItemInfo itmInfo)
{
// check the Word file extension that is saved in the tblDocuments SQL database table
DocumentInfo docInfo = itmInfo.MyContent.MyEntry.MyDocument;
if (docInfo.FileExtension.ToUpper() == ".DOCX") return; // already a DOCX - no need to convert
FrmPopupStatusMessage pmsg = null;
DSOFile myfile = null;
LBWordLibrary.LBApplicationClass ap = null;
LBWordLibrary.LBDocumentClass doc = null;
string orgFilename = null;
string filename = null;
FileInfo fi = null;
FileStream fs = null;
SectionInfo msi = null;
Section sec = null;
SectionConfig cfg = null;
try
{
// show user a status window of the Word section being converted to DOCX
// use the section number (DisplayNumber) unless the length is zero, then use the section title (DisplayText)
string statMsg = itmInfo.DisplayNumber;
if (statMsg.Length == 0)
statMsg = itmInfo.DisplayText;
pmsg = new FrmPopupStatusMessage("Converting This Section to Word DOCX", statMsg);
pmsg.Show();
// Get Document as file - it's placed in the user's temporary folder (like we do when we edit a Word section)
myfile = new DSOFile(docInfo);
// Open MSWord App
ap = new LBWordLibrary.LBApplicationClass();
doc = ap.Documents.Open(myfile.FullName);
// Older versions of PROMS saved the Word section as either a RTF or the old-style Word DOC file
// In either case, we want to convert it to a Word DOCX file
// So now create a file name with the .DOCX extension
orgFilename = myfile.FullName.ToUpper();
filename = orgFilename.Replace(".RTF", ".DOCX").Replace(".DOC", ".DOCX"); // we want to convert either .RTF or .DOC Word sections
// This calls Word's convert function to convert the opened .DOC or .RTF to DOCX and save it to our new DOCX file name
doc.SaveAs(filename, LBWordLibrary.LBWdSaveFormat.wdFormatXMLDocument); // Convert to Word DOCX
doc.Close();
doc = null;
// Now read in the new .DOCX file and save the contents to the SQL database
fi = new FileInfo(filename);
fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);// B2016-053
long len = fs.Length;
byte[] ByteArray = new byte[len];
int nBytesRead = fs.Read(ByteArray, 0, (int)len);
bool isLibraryDocument = (docInfo.LibTitle != null && docInfo.LibTitle != "");
Document myDoc = null;
if (isLibraryDocument)
myDoc = Document.Get(docInfo.DocID);
else
myDoc = Document.MakeDocument(null, ByteArray, docInfo.DocAscii, docInfo.Config, ".DOCX");
// update the document information in the database
msi = itmInfo as SectionInfo;
sec = msi.Get();
cfg = sec.SectionConfig;
if (!isLibraryDocument)
cfg.MySection.MyContent.MyEntry.MyDocument = myDoc; // resetting MyDocument will clear the library doc link - so don't do if a library document
else
cfg.MySection.MyContent.MyEntry.MyDocument.DocContent = ByteArray; // only update .DocContent for library documents
cfg.MySection.MyContent.MyEntry.MyDocument.FileExtension = ".DOCX"; // make sure the Word file extension is .DOCX
cfg.MySection.MyContent.MyEntry.MyDocument.DTS = fi.LastWriteTimeUtc;
cfg.MySection.MyContent.MyEntry.MyDocument.MarkDirty();
cfg.MySection.MyContent.MyEntry.Save();
_MyLog.InfoFormat("Converted Word Section to DOCX - Old ID {0} - New ID {1} - {2}", docInfo.DocID, myDoc.DocID, statMsg); // record in log file (aka error log) that conversion was done
// delete the temporary files
FileInfo orgFile = new FileInfo(orgFilename);
orgFile.Delete();// delete the old temporary Word file (.DOC or .RTF)
}
catch (Exception ex)
{
_MyLog.ErrorFormat("Error converting Word section to DOCX - {0}", ex.Message);
_MyLog.ErrorFormat("Error converting Word section to DOCX - ConvertWordSetionToDOXX: ItemID ={0} DOCID={1} LibTitle = {2}", itmInfo, docInfo.DocID, docInfo.LibTitle);
}
finally
{
if (pmsg != null)
pmsg.Close();// close the statue message
if (ap != null)
ap.Quit(); // close the Word app
if (doc != null)
doc.Close();
if (fs != null)
fs.Close();
if (fi != null && fi.Exists)
fi.Delete();// delete the temporary .DOCX file
}
}
/// <summary>
/// FixString processes the string returned and changes any symbols (0xF0??) to normal characters
/// </summary>

View File

@ -0,0 +1,72 @@

namespace Volian.Base.Library
{
partial class FrmPopupStatusMessage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.popMsg = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// popMsg
//
this.popMsg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.popMsg.Location = new System.Drawing.Point(13, 13);
this.popMsg.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.popMsg.Name = "popMsg";
this.popMsg.Size = new System.Drawing.Size(536, 16);
this.popMsg.TabIndex = 0;
this.popMsg.Text = "label1";
this.popMsg.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.popMsg.UseWaitCursor = true;
//
// FrmPopupStatusMessage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ClientSize = new System.Drawing.Size(562, 38);
this.ControlBox = false;
this.Controls.Add(this.popMsg);
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FrmPopupStatusMessage";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "FrmPopupStatusMessage";
this.TopMost = true;
this.UseWaitCursor = true;
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Label popMsg;
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Volian.Base.Library
{
public partial class FrmPopupStatusMessage : Form
{
// This creates a simple message box consisting of a title and the message
// The purpose is to allow the coder to pop up brief status message during the running of a method for a 3rd party.
// i.e. this is used when PROMS uses Word to convert to a DOCX file format for PROMS Word sections.
// The message is centered in the message box - we can expand on this class if needed
// The coder uses the Show method to display the message box and Close to remove it
// The user is not prompted for a response.
public FrmPopupStatusMessage(string title, string msg)
{
InitializeComponent();
Text = title;
popMsg.Text = msg;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -95,6 +95,12 @@
<Compile Include="FlagEnumEditor.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="FrmPopupStatusMessage.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FrmPopupStatusMessage.Designer.cs">
<DependentUpon>FrmPopupStatusMessage.cs</DependentUpon>
</Compile>
<Compile Include="frmRtfEdit.cs">
<SubType>Form</SubType>
</Compile>
@ -117,6 +123,9 @@
<Compile Include="VolianTimer.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="FrmPopupStatusMessage.resx">
<DependentUpon>FrmPopupStatusMessage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="frmRtfEdit.resx">
<DependentUpon>frmRtfEdit.cs</DependentUpon>
</EmbeddedResource>

View File

@ -655,6 +655,7 @@ namespace Volian.Controls.Library
}
else // Otherwise open it in the Word editor
{
Document.ConvertWordSectionToDOCX(myItemInfo); // B2023-093 Convert a Word section to the DOCX Word format if needed before opening it for edit
return OpenDSOTabPage(myItemInfo);
}
}

View File

@ -761,6 +761,10 @@ namespace Volian.Print.Library
int cnt = 0;
foreach (SectionInfo mySection in myProcedure.Sections)
{
if (!mySection.MyDocStyle.IsStepSection && !mySection.IsAutoTOCSection)
{
VEPROMS.CSLA.Library.Document.ConvertWordSectionToDOCX((ItemInfo)mySection); // B2023-093 Convert a Word section to the DOCX Word format if needed before printing
}
//C2019-042 Section_IsFoldout checks Section Number, Section Title, and use of check box
if ((myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.SectionLevelFoldouts && (mySection.MyConfig as SectionConfig).Section_IsFoldout == "Y")
|| (myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.AlternateFloatingFoldout && (mySection.MyConfig as SectionConfig).Section_IsFoldout == "Y"))