449 lines
14 KiB
C#
449 lines
14 KiB
C#
///
|
|
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Printing;
|
|
using System.IO;
|
|
using Config.Entities;
|
|
using TBF.Resources;
|
|
|
|
namespace TBF
|
|
{
|
|
public class PrintOrderDocument : PrintDocument
|
|
{
|
|
const string FontFamilyName = "Arial"; //"Times New Roman";
|
|
|
|
const int SpacingOne = 18;
|
|
const int Padding = 10;
|
|
const int TitleX = 100;
|
|
const int TitleY = 160;
|
|
int HdrTop = 220; /// Depends on the size of the title
|
|
int TableTopFirstPage = 390; /// Depends on the size of the header
|
|
int TableTopNextPage = TitleY;
|
|
|
|
const int SpacingOneAndHalf = (3 * SpacingOne) / 2;
|
|
|
|
/// <summary>
|
|
/// Property variable for the Font the user wishes to use
|
|
/// </summary>
|
|
Font font;
|
|
Font boldFont;
|
|
Font titleFont;
|
|
|
|
///
|
|
/// Data to print
|
|
///
|
|
readonly Procedure procedure;
|
|
readonly IList<TestResult> allResults;
|
|
readonly string tester;
|
|
readonly DateTime dateTime;
|
|
readonly int batchMin;
|
|
readonly int batchMax;
|
|
|
|
///
|
|
/// Items to print
|
|
///
|
|
readonly IList<string> testNames;
|
|
readonly int testsPerMeter;
|
|
readonly IList<Results.ItemSpec> resultItems;
|
|
|
|
///
|
|
/// Data to print
|
|
///
|
|
readonly int maxNrRows;
|
|
readonly int nrRows;
|
|
readonly int nrColumns;
|
|
string[,] dataToPrint;
|
|
|
|
///
|
|
/// Layout and status
|
|
///
|
|
int nrTabLinesOnFirstPage;
|
|
int nrTabLinesOnNextPage;
|
|
int nextTableRow; /// nr. of table row to be printed as the first one on the next page
|
|
int nrPages;
|
|
int pageNr; /// Page number to be printed at the bottom of the page
|
|
|
|
|
|
/// <summary>
|
|
/// Constructor.
|
|
/// Precalculates some values and dimensions and stores strings for the table
|
|
/// to be printed into a 2-dimensional array of strings 'dataToprint'.
|
|
/// </summary>
|
|
/// <param name="procedure">Procedure belonging to the results</param>
|
|
/// <param name="allResults">Results to be printed (multiple batches)</param>
|
|
public PrintOrderDocument(Procedure procedure, IList<TestResult> allResults, string tester)
|
|
{
|
|
this.procedure = procedure;
|
|
this.allResults = allResults;
|
|
this.tester = tester;
|
|
|
|
dateTime = DateTime.Now;
|
|
|
|
batchMin = int.MaxValue;
|
|
batchMax = int.MinValue;
|
|
foreach (var tr in allResults)
|
|
{
|
|
if (tr.BatchNr < batchMin) batchMin = tr.BatchNr;
|
|
if (tr.BatchNr > batchMax) batchMax = tr.BatchNr;
|
|
}
|
|
|
|
resultItems = Results.ItemSpec.FromStrArray(Program.LocalSettings.RsltItems_Printer_SingleWM);
|
|
|
|
testNames = Utils.GetDecoratedTestNames(procedure, 1);
|
|
testsPerMeter = testNames.Count;
|
|
|
|
maxNrRows = (batchMax - batchMin + 1) * Config.Data.WMsCount;
|
|
nrColumns = testsPerMeter * resultItems.Count + 2;
|
|
|
|
///
|
|
/// Prepare raw data to print
|
|
///
|
|
dataToPrint = new string[maxNrRows, nrColumns];
|
|
nrRows = 0;
|
|
for (int i = batchMin; i <= batchMax; i++)
|
|
{
|
|
/// Collect all results belonging to one batch
|
|
IList<TestResult> unsortedResults = new List<TestResult>();
|
|
foreach (var tr in allResults) if (tr.BatchNr == i) unsortedResults.Add(tr);
|
|
|
|
if (unsortedResults.Count == 0) continue;
|
|
|
|
for (int wmNr = 0; wmNr < Config.Data.WMsCount; wmNr++) /// wmNr is 0-based
|
|
{
|
|
if (!unsortedResults[0].Meters[wmNr].Disabled)
|
|
{
|
|
dataToPrint[nrRows, 0] = (nrRows + 1).ToString();
|
|
dataToPrint[nrRows, 1] = unsortedResults[0].Meters[wmNr].SerialNr;
|
|
|
|
IList<TestResult> results =
|
|
Utils.GetSortedTestResults(procedure, unsortedResults, Utils.PartNr(wmNr + 1, false));
|
|
|
|
for (int j = 0; j < testsPerMeter; j++)
|
|
{
|
|
if (results[j] != null)
|
|
{
|
|
int k = 2 + j * resultItems.Count;
|
|
foreach (var item in resultItems)
|
|
{
|
|
///TODO
|
|
//string str = item.Print(results[j].Meters[wmNr]);
|
|
//int pos = str.IndexOf('|');
|
|
//dataToPrint[nrRows, k++] = (pos < 0) ? str : str.Substring(0, pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
nrRows++;
|
|
}
|
|
}
|
|
}
|
|
|
|
pageNr = 1;
|
|
nextTableRow = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override the default onbeginPrint method of the PrintDocument Object
|
|
/// </summary>
|
|
/// <param name=e></param>
|
|
/// <remarks></remarks>
|
|
protected override void OnBeginPrint(System.Drawing.Printing.PrintEventArgs e)
|
|
{
|
|
base.OnBeginPrint(e);
|
|
|
|
if (font == null) { font = new Font(FontFamilyName, 10, FontStyle.Regular); }
|
|
if (boldFont == null) { boldFont = new Font(FontFamilyName, 10, FontStyle.Bold); }
|
|
if (titleFont == null) { titleFont = new Font(FontFamilyName, 18, FontStyle.Bold); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override the default OnPrintPage method of the PrintDocument.
|
|
/// </summary>
|
|
/// <param name=e></param>
|
|
/// <remarks>This provides the print logic for our document</remarks>
|
|
protected override void OnPrintPage(System.Drawing.Printing.PrintPageEventArgs e)
|
|
{
|
|
/// Run base code
|
|
base.OnPrintPage(e);
|
|
|
|
/// Set print area size and margins (in dots using 80 dpi)
|
|
int printHeight = base.DefaultPageSettings.PaperSize.Height - base.DefaultPageSettings.Margins.Top - base.DefaultPageSettings.Margins.Bottom;
|
|
int printWidth = base.DefaultPageSettings.PaperSize.Width - base.DefaultPageSettings.Margins.Left - base.DefaultPageSettings.Margins.Right;
|
|
int leftMargin = base.DefaultPageSettings.Margins.Left; /// X
|
|
int topMargin = base.DefaultPageSettings.Margins.Top; /// Y
|
|
|
|
if (base.DefaultPageSettings.Landscape)
|
|
{
|
|
/// Landscape mode: we need to swap height/width parameters
|
|
int tmp = printHeight;
|
|
printHeight = printWidth;
|
|
printWidth = tmp;
|
|
|
|
if (File.Exists("C:\\TBF\\header-landscape.png"))
|
|
{
|
|
Image img = Image.FromFile("C:\\TBF\\header-landscape.png");
|
|
e.Graphics.DrawImage(new Bitmap(img), new Rectangle(0, 0, 1169, 827));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (File.Exists("C:\\TBF\\header-portrait.png"))
|
|
{
|
|
Image img = Image.FromFile("C:\\TBF\\header-portrait.png");
|
|
e.Graphics.DrawImage(new Bitmap(img), new Rectangle(0, 0, 827, 1169));
|
|
}
|
|
}
|
|
|
|
///---------------
|
|
/// Common info
|
|
///---------------
|
|
if (pageNr == 1)
|
|
{
|
|
if (!string.IsNullOrEmpty(allResults[0].ProtocolTitle))
|
|
{
|
|
RectangleF printArea = new RectangleF(TitleX, TitleY, 667, 40);
|
|
e.Graphics.DrawString(allResults[0].ProtocolTitle, titleFont, Brushes.Black, printArea);
|
|
}
|
|
else
|
|
{
|
|
TableTopFirstPage -= (HdrTop - TitleY);
|
|
HdrTop = TitleY;
|
|
}
|
|
|
|
string[] leftColumn = new string[]
|
|
{
|
|
Strings.Purchase_order_,
|
|
Strings.Date_and_time_,
|
|
Strings.Procedure_,
|
|
Strings.Tester_,
|
|
Strings.Approval_,
|
|
Strings.Ambient_temperature_,
|
|
Strings.Ambient_pressure_,
|
|
Strings.Ambient_humidity_,
|
|
};
|
|
|
|
string[] rightColumn = new string[]
|
|
{
|
|
allResults[0].PurchaseOrder,
|
|
//dateTime.ToShortDateString() + " " + dateTime.ToShortTimeString(),
|
|
string.Format("{0}.{1}.{2} {3}:{4}", dateTime.Year.ToString("D4"),
|
|
dateTime.Month.ToString("D2"),
|
|
dateTime.Day.ToString("D2"),
|
|
dateTime.Hour.ToString("D2"),
|
|
dateTime.Minute.ToString("D2")),
|
|
procedure.Name,
|
|
tester,
|
|
string.Empty,
|
|
allResults[0].AmbientTempAve.ToString("F1") + " °C",
|
|
allResults[0].AmbientPressAve.ToString("F0") + " mbar",
|
|
allResults[0].AmbientHumiAve.ToString("F0") + " %",
|
|
};
|
|
|
|
/// Determine max. left column width in characters
|
|
float maxWdth = 0;
|
|
foreach (var s in leftColumn)
|
|
{
|
|
float wdth = e.Graphics.MeasureString(s, font).Width;
|
|
if (wdth > maxWdth) maxWdth = wdth;
|
|
}
|
|
|
|
/// Write aligned columns
|
|
for (int i = 0; i < Math.Min(leftColumn.Length, rightColumn.Length); i++)
|
|
{
|
|
PrintAt(e, 100, HdrTop + SpacingOne * i, leftColumn[i]);
|
|
PrintAt(e, 100 + (int)maxWdth + 20, HdrTop + SpacingOne * i, rightColumn[i]);
|
|
}
|
|
}
|
|
|
|
///----------------
|
|
/// More pages ?
|
|
///----------------
|
|
if (pageNr == 1)
|
|
{
|
|
/// Determine the number of pages once
|
|
nrTabLinesOnNextPage = (topMargin + printHeight - TableTopNextPage - 70) / SpacingOne;
|
|
nrTabLinesOnFirstPage = (topMargin + printHeight - TableTopFirstPage - 70) / SpacingOne;
|
|
|
|
if (nrRows <= nrTabLinesOnFirstPage)
|
|
{
|
|
nrPages = 1;
|
|
}
|
|
else
|
|
{
|
|
nrPages = 1 + ((nrRows - nrTabLinesOnFirstPage) + nrTabLinesOnNextPage - 1) / nrTabLinesOnNextPage;
|
|
}
|
|
}
|
|
int nrTabLinesOnThisPage = (pageNr == 1) ? nrTabLinesOnFirstPage : nrTabLinesOnNextPage;
|
|
int rowFrom = nextTableRow;
|
|
int rowTo;
|
|
if (nrRows <= nextTableRow + nrTabLinesOnThisPage)
|
|
{
|
|
rowTo = nrRows - 1;
|
|
e.HasMorePages = false;
|
|
}
|
|
else
|
|
{
|
|
rowTo = rowFrom + nrTabLinesOnThisPage - 1;
|
|
nextTableRow = rowFrom + nrTabLinesOnThisPage;
|
|
e.HasMorePages = true;
|
|
}
|
|
|
|
///--------
|
|
/// Body
|
|
///--------
|
|
int[] columnPos = GetColumnPositions(e, dataToPrint, rowFrom, rowTo, leftMargin + Padding, 2 * Padding);
|
|
int tableLeft = leftMargin;
|
|
int tableRight = columnPos[nrColumns] - Padding;
|
|
|
|
int currentTableTop = (pageNr == 1) ? TableTopFirstPage : TableTopNextPage;
|
|
int yyy = currentTableTop;
|
|
|
|
/// Horizontal line
|
|
e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeft, yyy), new Point(tableRight, yyy));
|
|
yyy += 2;
|
|
|
|
/// Line with test names (larger columns, names centered)
|
|
for (int bigcol = 0; bigcol < testsPerMeter; bigcol++)
|
|
{
|
|
float width = e.Graphics.MeasureString(testNames[bigcol], font).Width;
|
|
int bc = 2 + bigcol * resultItems.Count;
|
|
int xxx = (columnPos[bc] + columnPos[bc + resultItems.Count]) / 2 - Padding - (int)(width / 2 + 0.5f);
|
|
PrintAt(e, xxx, yyy, testNames[bigcol]);
|
|
}
|
|
yyy += SpacingOne;
|
|
|
|
int tableTop2 = yyy;
|
|
|
|
/// Indented horizontal line
|
|
e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(columnPos[2] - Padding, yyy), new Point(tableRight, yyy));
|
|
yyy += 2;
|
|
|
|
/// Line with header texts
|
|
PrintAt(e, columnPos[0], yyy - SpacingOne / 2, GetHeaderItem(0));
|
|
PrintAt(e, columnPos[1], yyy - SpacingOne / 2, GetHeaderItem(1));
|
|
for (int col = 2; col < nrColumns; col++)
|
|
{
|
|
PrintAt(e, columnPos[col], yyy, GetHeaderItem(col));
|
|
}
|
|
yyy += SpacingOne;
|
|
|
|
/// Horizontal line
|
|
e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeft, yyy), new Point(tableRight, yyy));
|
|
yyy += 2;
|
|
|
|
/// Table with results
|
|
for (int row = rowFrom; row <= rowTo; row++)
|
|
{
|
|
for (int col = 0; col < nrColumns; col++)
|
|
{
|
|
PrintAt(e, columnPos[col], yyy, dataToPrint[row, col]);
|
|
}
|
|
yyy += SpacingOne;
|
|
}
|
|
|
|
/// Horizontal line
|
|
e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(tableLeft, yyy), new Point(tableRight, yyy));
|
|
int tableBottom = yyy;
|
|
|
|
/// Vertical lines
|
|
for (int col = 0; col <= nrColumns; col++)
|
|
{
|
|
if (col < 2 || ((col-2) % resultItems.Count) == 0)
|
|
{
|
|
e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(columnPos[col] - Padding, currentTableTop),
|
|
new Point(columnPos[col] - Padding, tableBottom));
|
|
}
|
|
else
|
|
{
|
|
e.Graphics.DrawLine(new Pen(Color.Black, 2), new Point(columnPos[col] - Padding, tableTop2),
|
|
new Point(columnPos[col] - Padding, tableBottom));
|
|
}
|
|
}
|
|
|
|
///----------
|
|
/// Footer
|
|
///----------
|
|
PrintAt(e, leftMargin, topMargin + printHeight - SpacingOne, string.Format("{0} {1}/{2}", Strings.Page, pageNr++, nrPages));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns header text for each column of the table.
|
|
/// </summary>
|
|
/// <param name="column">COlumn nymber (0-based)</param>
|
|
/// <returns>Header text</returns>
|
|
string GetHeaderItem(int column)
|
|
{
|
|
switch (column)
|
|
{
|
|
case 0: return "Nr.";
|
|
case 1: return "S/N";
|
|
default: return resultItems[(column - 2) % resultItems.Count].ClmnHeaderText;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determine column widths and return column left positions for a subset of table rows
|
|
/// </summary>
|
|
/// <param name="dataToPrint">string[nrRows, nrColumns]</param>
|
|
/// <param name="rowFrom">First row to consider</param>
|
|
/// <param name="rowTo">Last row to consider</param>
|
|
/// <returns>Left column positions and right side float[nrColumns + 1]</returns>
|
|
int[] GetColumnPositions(System.Drawing.Printing.PrintPageEventArgs e,
|
|
string[,] dataToPrint, int rowFrom, int rowTo,
|
|
int leftMargin, int padding)
|
|
{
|
|
int nrColumns = dataToPrint.GetLength(1);
|
|
int[] columnPos = new int[nrColumns + 1];
|
|
columnPos[0] = leftMargin;
|
|
|
|
for (int column = 0; column < nrColumns; column++)
|
|
{
|
|
float columnWidth = e.Graphics.MeasureString(GetHeaderItem(column), font).Width;
|
|
|
|
for (int row = rowFrom; row <= rowTo; row++)
|
|
{
|
|
float itemWidth = e.Graphics
|
|
.MeasureString(dataToPrint[row, column] == null ? string.Empty : dataToPrint[row, column], font)
|
|
.Width;
|
|
if (itemWidth > columnWidth) columnWidth = itemWidth;
|
|
}
|
|
|
|
columnPos[column + 1] = columnPos[column] + (int)(columnWidth + 0.5f) + padding;
|
|
}
|
|
|
|
return columnPos;
|
|
}
|
|
|
|
|
|
void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, Point p, string text)
|
|
{
|
|
PrintAt(e, p.X, p.Y, text);
|
|
}
|
|
|
|
void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, int x, int y, string text)
|
|
{
|
|
RectangleF printArea = new RectangleF(x, y, 667, SpacingOne);
|
|
e.Graphics.DrawString(text, this.font, Brushes.Black, printArea);
|
|
}
|
|
|
|
void PrintBoldAt(System.Drawing.Printing.PrintPageEventArgs e, Point p, string text)
|
|
{
|
|
PrintBoldAt(e, p.X, p.Y, text);
|
|
}
|
|
|
|
void PrintBoldAt(System.Drawing.Printing.PrintPageEventArgs e, int x, int y, string text)
|
|
{
|
|
RectangleF printArea = new RectangleF(x, y, 667, SpacingOne);
|
|
e.Graphics.DrawString(text, this.boldFont, Brushes.Black, printArea);
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|