コード例 #1
0
ファイル: Excel.cs プロジェクト: Davincier/openpetra
        private String GetRowDescr(TResult row)
        {
            String ReturnValue;

            ReturnValue = "";

            if ((row.header != null) && (row.header[0].ToString().Length > 0))
            {
                if (ReturnValue.Length > 0)
                {
                    ReturnValue = ReturnValue + " ";
                }

                ReturnValue = ReturnValue + row.header[0].ToString();
            }

            if ((row.header != null) && (row.header[1].ToString().Length > 0))
            {
                if (ReturnValue.Length > 0)
                {
                    ReturnValue = ReturnValue + " ";
                }

                ReturnValue = ReturnValue + row.header[1].ToString();
            }

            if ((row.descr != null) && (row.descr[0].ToString().Length > 0))
            {
                if (ReturnValue.Length > 0)
                {
                    ReturnValue = ReturnValue + " ";
                }

                ReturnValue = ReturnValue + row.descr[0].ToString();
            }

            if ((row.descr != null) && (row.descr[1].ToString().Length > 0))
            {
                if (ReturnValue.Length > 0)
                {
                    ReturnValue = ReturnValue + " ";
                }

                ReturnValue = ReturnValue + row.descr[1].ToString();
            }

            return ReturnValue;
        }
コード例 #2
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// find the next sibling of the parent row
        /// </summary>
        /// <param name="currentRow"></param>
        /// <returns></returns>
        protected TResult FindNextUncle(TResult currentRow)
        {
            TResult ReturnValue;

            ReturnValue = null;

            if (currentRow.masterRow > 0)
            {
                ReturnValue = FindNextRow(FindRow(currentRow.masterRow));
            }

            if (ReturnValue != null)
            {
                FNextElementLineToPrint[ReturnValue.depth] = eStageElementPrinting.eHeader;
            }

            return ReturnValue;
        }
コード例 #3
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// find the next row on the same level
        /// </summary>
        /// <param name="currentRow"></param>
        /// <returns></returns>
        protected TResult FindNextSibling(TResult currentRow)
        {
            TResult ReturnValue;
            Int32 i;
            Int32 masterRow;
            Int32 childRow;

            // if currentRow is nil assume the root (needed to find first printable element)
            if (currentRow != null)
            {
                masterRow = currentRow.masterRow;
                childRow = currentRow.childRow;
            }
            else
            {
                masterRow = 0;
                childRow = 0;
            }

            ReturnValue = null;

            foreach (TResult row in FResults)
            {
                if (row.masterRow == masterRow)
                {
                    if ((row.childRow > childRow) && ((ReturnValue == null) || (row.childRow < ReturnValue.childRow)))
                    {
                        if ((row.depth == 1) && (FLowestLevel != 1)
                            && (FParameters.GetOrDefault("HasSubReports", -1, new TVariant(false)).ToBool() == true))
                        {
                            // reset the FLowestLevel, because this is basically a new report (several lowerlevelreports in main level)
                            // todo: be careful: some reports have several rows in the main level, I just assumed one total for the finance reports
                            // it works now for reports with just one row depth, for others this still needs to be sorted properly. another parameter?
                            FLowestLevel = FResultList.GetDeepestVisibleLevel(row.childRow);
                            FPrinter.LineSpaceFeed(eFont.eDefaultFont);
                            FPrinter.DrawLine(FPrinter.LeftMargin, FPrinter.RightMargin, eLinePosition.eAbove, eFont.eDefaultBoldFont);
                            FPrinter.LineSpaceFeed(eFont.eDefaultFont);
                            FParameters.Add("CurrentSubReport", FParameters.Get("CurrentSubReport").ToInt() + 1);

                            for (i = 0; i <= FLowestLevel; i += 1)
                            {
                                FNextElementLineToPrint.Add(eStageElementPrinting.eHeader);
                            }

                            FNextElementLineToPrint[FLowestLevel] = eStageElementPrinting.eDetails;
                        }

                        ReturnValue = row;
                        FNextElementLineToPrint[ReturnValue.depth] = eStageElementPrinting.eHeader;
                    }
                }
            }

            return ReturnValue;
        }
コード例 #4
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// find first row that is in the hierarchy below the current row
        /// </summary>
        /// <param name="currentRow"></param>
        /// <returns></returns>
        protected TResult FindFirstChild(TResult currentRow)
        {
            TResult ReturnValue;

            ReturnValue = null;

            foreach (TResult row in FResults)
            {
                if ((row.masterRow == currentRow.childRow) && (row.depth <= FLowestLevel))
                {
                    if ((ReturnValue == null) || (row.childRow < ReturnValue.childRow))
                    {
                        ReturnValue = row;
                    }
                }
            }

            return ReturnValue;
        }
コード例 #5
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
 /// <summary>
 /// can either print or simulate
 /// </summary>
 /// <returns>s the current y position after printing or simulating
 /// </returns>
 protected virtual double PrintNormalLevelFooter(TResult row)
 {
     return 0.0;
 }
コード例 #6
0
ファイル: Result.cs プロジェクト: Davincier/openpetra
 /// <summary>
 /// copy constructor; creates a copy of the given object
 ///
 /// </summary>
 /// <returns>void</returns>
 public TResult(TResult copy)
 {
     Assign(copy);
 }
コード例 #7
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
 /// <summary>
 /// print the lowest level (no children)
 /// </summary>
 /// <param name="row"></param>
 /// <returns></returns>
 protected virtual Boolean PrintLowestLevel(TResult row)
 {
     return false;
 }
コード例 #8
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// print a normal level
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        protected Boolean PrintNormalLevel(TResult row)
        {
            if ((eStageElementPrinting)FNextElementLineToPrint[row.depth] == eStageElementPrinting.eHeader)
            {
                if (!PrintNormalLevelHeader(row))
                {
                    return false;
                }
            }

            if ((eStageElementPrinting)FNextElementLineToPrint[row.depth] == eStageElementPrinting.eDetails)
            {
                if (!PrintNormalLevelDetails(row))
                {
                    return false;
                }
            }

            if ((eStageElementPrinting)FNextElementLineToPrint[row.depth] == eStageElementPrinting.eFooter)
            {
                // try if footer will still fit on the page; it can consist of 2 lines, and there is no page length check in there
                FPrinter.StartSimulatePrinting();
                PrintNormalLevelFooter(row);

                if (!FPrinter.ValidYPos())
                {
                    // not enoughSpace
                    FPrinter.FinishSimulatePrinting();
                    FNextElementLineToPrint[row.depth] = eStageElementPrinting.eFooter;
                    FNextElementToPrint = row.childRow;
                    return false;
                }

                FPrinter.FinishSimulatePrinting();
                PrintNormalLevelFooter(row);
            }

            return true;
        }
コード例 #9
0
ファイル: PrinterLayout.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// print the lowest level (has no child levels)
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        protected override Boolean PrintLowestLevel(TResult row)
        {
            Boolean ReturnValue;
            String descr0 = "";
            String descr1 = "";

            if (!FPrinter.ValidYPos())
            {
                // not enoughSpace
                ReturnValue = false;
                FNextElementToPrint = row.childRow;
                FNextElementLineToPrint[row.depth] = eStageElementPrinting.eDetails;
            }
            else
            {
                // can either print descr or header
                if ((row.descr != null) && (row.descr[0].ToString().Length > 0))
                {
                    descr0 = row.descr[0].ToString();
                }
                else if ((row.header != null) && (row.header[0].ToString().Length > 0))
                {
                    descr0 = row.header[0].ToString();
                }

                if ((row.descr != null) && (row.descr[1].ToString().Length > 0))
                {
                    descr1 = row.descr[1].ToString();
                }
                else if ((row.header != null) && (row.header[1].ToString().Length > 0))
                {
                    descr1 = row.header[1].ToString();
                }

                FPrinter.PrintString(descr0, eFont.eDefaultFont, GetPosition(ReportingConsts.COLUMNLEFT + 1, row.depth,
                        FPrinter.Cm(COLUMNLEFT1_POS)),
                    GetWidth(ReportingConsts.COLUMNLEFT + 1,
                        row.depth,
                        FPrinter.Cm(1)),
                    GetAlignment(ReportingConsts.COLUMNLEFT + 1,
                        row.depth, eAlignment.eLeft));
                FPrinter.PrintString(descr1, eFont.eDefaultFont, GetPosition(ReportingConsts.COLUMNLEFT + 2,
                        row.depth,
                        FPrinter.Cm(COLUMNLEFT2_POS)),
                    GetWidth(ReportingConsts.COLUMNLEFT + 2, row.depth,
                        FPrinter.Cm(3)),
                    GetAlignment(ReportingConsts.COLUMNLEFT + 2,
                        row.depth, eAlignment.eLeft));
                PrintColumns(row);
                FNextElementLineToPrint[row.depth] = eStageElementPrinting.eFinished;
                ReturnValue = true;
            }

            return ReturnValue;
        }
コード例 #10
0
ファイル: PrinterLayout.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// print all columns of a given row
        /// </summary>
        /// <param name="ARow"></param>
        /// <returns></returns>
        protected bool PrintColumns(TResult ARow)
        {
            Int32 columnNr;
            float YPosBefore;
            float LowestYPos;

            YPosBefore = FPrinter.CurrentYPos;

            // we need at least one row, otherwise the strings on the left are written in the same row
            FPrinter.LineFeed(eFont.eDefaultFont);
            LowestYPos = FPrinter.CurrentYPos;

            for (columnNr = 0; columnNr <= FNumberColumns - 1; columnNr += 1)
            {
                FPrinter.CurrentYPos = YPosBefore;
                PrintColumn(columnNr, ARow.depth, ARow.column[columnNr]);

                // store the highest column
                if (FPrinter.CurrentYPos > LowestYPos)
                {
                    LowestYPos = FPrinter.CurrentYPos;
                }
            }

            FPrinter.CurrentYPos = LowestYPos;
            return true;
        }
コード例 #11
0
ファイル: CalculationRow.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// recalculate row after all the columns have been calculated already,
        /// but now the functions based on other columns are calculated.
        /// </summary>
        /// <param name="situation"></param>
        /// <param name="row"></param>
        public static void RecalculateRow(TRptSituation situation, TResult row)
        {
            int counter;
            string strCalculation;
            TVariant ColumnCalc;
            TVariant levelCalc;
            TRptDataCalcResult rptDataCalcResult;
            String ColumnFormat;
            TVariant value;

            for (counter = 0; counter <= row.column.Length - 1; counter += 1)
            {
                // calculation is used for display in the GUI, formula is used for adding ledgers
                ColumnCalc = situation.GetParameters().Get("param_formula", counter, -1, eParameterFit.eExact);

                if (ColumnCalc.IsZeroOrNull())
                {
                    ColumnCalc = situation.GetParameters().Get("param_calculation", counter, -1, eParameterFit.eExact);
                }

                levelCalc = situation.GetParameters().Get("param_formula", ReportingConsts.ALLCOLUMNS, row.depth, eParameterFit.eExact);

                if (levelCalc.IsZeroOrNull())
                {
                    levelCalc = situation.GetParameters().Get("param_calculation", ReportingConsts.ALLCOLUMNS, row.depth, eParameterFit.eExact);
                }

                strCalculation = "";

                if ((!ColumnCalc.IsZeroOrNull() && situation.GetReportStore().IsFunctionCalculation(situation.GetCurrentReport(), ColumnCalc.ToString())))
                {
                    // e.g. add(Column(1), Column(2))
                    strCalculation = ColumnCalc.ToString();
                }
                else if ((!levelCalc.IsZeroOrNull()
                          && situation.GetReportStore().IsFunctionCalculation(situation.GetCurrentReport(), levelCalc.ToString())))
                {
                    // e.g. getSumLowerReport
                    strCalculation = levelCalc.ToString();
                }

                if (situation.GetReportStore().IsFunctionCalculation(situation.GetCurrentReport(), strCalculation))
                {
                    rptDataCalcResult = new TRptDataCalcResult(situation, row.depth, counter, row.childRow, row.masterRow);
                    ColumnFormat = "";

                    if (situation.GetParameters().Exists("ColumnFormat", counter, row.depth))
                    {
                        ColumnFormat = situation.GetParameters().Get("ColumnFormat", counter, row.depth).ToString();
                    }

                    value = rptDataCalcResult.Precalculate(row.column);
                    value.ApplyFormatString(ColumnFormat);

                    if (value.ToFormattedString().Length > 0)
                    {
                        row.column[counter] = value;
                    }
                }
            }
        }
コード例 #12
0
ファイル: Result.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// sort the results by their childrow code; using sort by insertion
        /// needed for excel export
        /// </summary>
        /// <returns>void</returns>
        public Boolean SortChildren()
        {
            int left = 0;
            int right = results.Count - 1;

            for (int i = left + 1; i <= right; i += 1)
            {
                int j = i;
                TResult current = (TResult)results[j];
                TResult tempRow = new TResult(current);
                TResult previous;

                if (j > left)
                {
                    previous = (TResult)results[j - 1];
                }
                else
                {
                    previous = null;
                }

                while ((j > left) && (previous.childRow > tempRow.childRow))
                {
                    current = (TResult)results[j];
                    current.Assign(previous);
                    j--;

                    if (j > left)
                    {
                        previous = (TResult)results[j - 1];
                    }
                    else
                    {
                        previous = null;
                    }
                }

                current = (TResult)results[j];
                current.Assign(tempRow);
            }

            return true;
        }
コード例 #13
0
ファイル: Result.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// add a row to the result
        /// </summary>
        /// <param name="masterRow"></param>
        /// <param name="childRow"></param>
        /// <param name="display"></param>
        /// <param name="depth"></param>
        /// <param name="code"></param>
        /// <param name="condition"></param>
        /// <param name="debit_credit_indicator"></param>
        /// <param name="header"></param>
        /// <param name="descr"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public TResult AddRow(int masterRow,
            int childRow,
            Boolean display,
            int depth,
            String code,
            string condition,
            Boolean debit_credit_indicator,
            TVariant[] header,
            TVariant[] descr,
            TVariant[] column)
        {
//
// I wonder why we care about this "duplicate code"? Certainly this code generates lots of warnings, but reports are still generated OK:

/*
 *          foreach (TResult existingElement in results)
 *          {
 *              if (existingElement.code == code)
 *              {
 *                  TLogging.Log("Warning: TResult.AddRow: duplicate row codes! there is already a row with code " +
 *                      code);
 *                  // throw new Exception("TResult.AddRow: duplicate row codes! there is already a row with code " +
 *                  //    code);
 *              }
 *          }
 */
            TResult element = new TResult(masterRow, childRow, display, depth, code, condition, debit_credit_indicator, header, descr, column);

            results.Add(element);
            return element;
        }
コード例 #14
0
ファイル: Result.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// copies the values of the given object into the self object
        ///
        /// </summary>
        /// <returns>void</returns>
        public void Assign(TResult copy)
        {
            int i;

            this.masterRow = copy.masterRow;
            this.childRow = copy.childRow;
            this.display = copy.display;
            this.depth = copy.depth;
            this.code = copy.code;
            this.condition = copy.condition;
            this.debit_credit_indicator = copy.debit_credit_indicator;

            for (i = 0; i <= 1; i += 1)
            {
                this.header[i] = new TVariant(copy.header[i]);
            }

            for (i = 0; i <= 1; i += 1)
            {
                this.descr[i] = new TVariant(copy.descr[i]);
            }

            column = new TVariant[copy.column.Length];

            for (i = 0; i < copy.column.Length; i += 1)
            {
                this.column[i] = new TVariant(copy.column[i]);
            }
        }
コード例 #15
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// find the next sibling of currentRow.
        /// if there is none, then try to find the next row up one hierarchy
        /// if currentRow is the last row, return nil
        ///
        /// </summary>
        /// <returns>void</returns>
        protected TResult FindNextRow(TResult currentRow)
        {
            TResult ReturnValue;

            ReturnValue = FindNextSibling(currentRow);

            if ((ReturnValue == null) && (currentRow.masterRow > 0))
            {
                // see if the father is already fully printed
                ReturnValue = FindRow(currentRow.masterRow);

                if (ReturnValue != null)
                {
                    if ((eStageElementPrinting)FNextElementLineToPrint[ReturnValue.depth] == eStageElementPrinting.eFinished)
                    {
                        ReturnValue = null;
                    }
                    else
                    {
                        FNextElementLineToPrint[ReturnValue.depth] = eStageElementPrinting.eFooter;
                    }
                }
            }

            if (ReturnValue == null)
            {
                ReturnValue = FindNextUncle(currentRow);
            }

            return ReturnValue;
        }
コード例 #16
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// print the details of a normal level (not lowest level)
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        protected Boolean PrintNormalLevelDetails(TResult row)
        {
            Boolean ReturnValue;
            TResult childRow;

            FNextElementLineToPrint[row.depth] = eStageElementPrinting.eDetails;
            childRow = FindFirstChild(row);

            while (childRow != null)
            {
                FNextElementLineToPrint[childRow.depth] = eStageElementPrinting.eHeader;

                if (!PrintRow(childRow))
                {
                    return false;
                }

                childRow = FindNextSibling(childRow);
            }

            ReturnValue = true;
            FNextElementLineToPrint[row.depth] = eStageElementPrinting.eFooter;
            return ReturnValue;
        }
コード例 #17
0
ファイル: PrinterLayout.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// print the header of a normal level
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        protected override Boolean PrintNormalLevelHeader(TResult row)
        {
            Boolean ReturnValue;
            Boolean linePrinted;

            if (!FPrinter.ValidYPos())
            {
                // not enoughSpace
                FNextElementToPrint = row.childRow;
                FNextElementLineToPrint[row.depth] = eStageElementPrinting.eHeader;
                ReturnValue = false;
            }
            else
            {
                linePrinted = FPrinter.PrintString(row.header[0].ToString(),
                    eFont.eDefaultFont,
                    GetPosition(ReportingConsts.HEADERCOLUMN + 1, row.depth,
                        FPrinter.Cm(COLUMNLEFT1_POS)),
                    GetWidth(ReportingConsts.HEADERCOLUMN + 1, row.depth,
                        FPrinter.Cm(3)),
                    GetAlignment(ReportingConsts.HEADERCOLUMN + 1, row.depth, eAlignment.eLeft));
                linePrinted = FPrinter.PrintString(row.header[1].ToString(),
                    eFont.eDefaultFont,
                    GetPosition(ReportingConsts.HEADERCOLUMN + 2, row.depth,
                        FPrinter.Cm(COLUMNLEFT2_POS)),
                    GetWidth(ReportingConsts.HEADERCOLUMN + 2, row.depth,
                        FPrinter.Cm(3)),
                    GetAlignment(ReportingConsts.HEADERCOLUMN + 1, row.depth, eAlignment.eLeft))
                              || linePrinted;

                if (linePrinted)
                {
                    FPrinter.LineFeed(eFont.eDefaultFont);
                }

                ReturnValue = true;
            }

            FNextElementLineToPrint[row.depth] = eStageElementPrinting.eDetails;
            return ReturnValue;
        }
コード例 #18
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// prints the current Row
        /// </summary>
        /// <returns>s true if all were printed; false if page was full
        /// side effects: will set the NextElementToPrint
        /// </returns>
        protected Boolean PrintRow(TResult row)
        {
            Boolean ReturnValue;
            bool LowestLevel;

            LowestLevel = false;

            if (FindFirstChild(row) == null)
            {
                // if both descr and header are set, don't use lowestlevel, but normal level
                // to print both.
                // situations to test:
                // a) Account Detail, acc/cc with no transaction, but a balance
                // b) some situation with analysis attributes on account detail
                if ((row.descr == null) || (row.header == null))
                {
                    LowestLevel = true;
                }
            }

            if (row.depth == FLowestLevel)
            {
                LowestLevel = true;
            }

            if (LowestLevel)
            {
                if (!PrintLowestLevel(row))
                {
                    return false;
                }
            }
            else
            {
                if (!PrintNormalLevel(row))
                {
                    return false;
                }
            }

            ReturnValue = true;
            FNextElementToPrint = -1;
            return ReturnValue;
        }
コード例 #19
0
ファイル: PrinterLayout.cs プロジェクト: Davincier/openpetra
        /// <summary>
        /// can either print or simulate
        /// </summary>
        /// <returns>s the current y position after printing or simulating
        /// </returns>
        protected override double PrintNormalLevelFooter(TResult row)
        {
            Boolean linePrinted;

            linePrinted = false;

            // footer
            if (FParameters.Get("SpaceLineAbove", -1, row.depth, eParameterFit.eExact).ToBool() == true)
            {
                FPrinter.LineSpaceFeed(eFont.eDefaultFont);
            }

            if (FParameters.Get("FullLineAbove", -1, row.depth, eParameterFit.eExact).ToBool() == true)
            {
                FPrinter.DrawLine(FPrinter.LeftMargin, FPrinter.Width, eLinePosition.eAbove, eFont.eDefaultFont);
                FPrinter.LineSpaceFeed(eFont.eDefaultFont);
            }

            FPrinter.PrintString(row.descr[0].ToString(), eFont.eDefaultFont,
                GetPosition(ReportingConsts.COLUMNLEFT + 1, row.depth,
                    FPrinter.Cm(COLUMNLEFT1_POS)),
                GetWidth(ReportingConsts.COLUMNLEFT + 1, row.depth, FPrinter.Cm(3)),
                GetAlignment(ReportingConsts.COLUMNLEFT + 1, row.depth, eAlignment.eLeft));
            PrintColumns(row);
            linePrinted = FPrinter.PrintString(row.descr[1].ToString(), eFont.eDefaultFont,
                GetPosition(ReportingConsts.COLUMNLEFT + 1, row.depth,
                    FPrinter.Cm(COLUMNLEFT1_POS)),
                GetWidth(ReportingConsts.COLUMNLEFT + 1, row.depth, FPrinter.Cm(3)),
                GetAlignment(ReportingConsts.COLUMNLEFT + 1, row.depth, eAlignment.eLeft));

            if (linePrinted)
            {
                FPrinter.LineFeed(eFont.eDefaultFont);
            }

            if (FParameters.Get("FullLineBelow", -1, row.depth, eParameterFit.eExact).ToBool() == true)
            {
                FPrinter.DrawLine(FPrinter.LeftMargin, FPrinter.Width, eLinePosition.eAbove, eFont.eDefaultFont);
                FPrinter.LineSpaceFeed(eFont.eDefaultFont);
            }

            if (FParameters.Get("SpaceLineBelow", -1, row.depth, eParameterFit.eExact).ToBool() == true)
            {
                FPrinter.LineSpaceFeed(eFont.eDefaultFont);
            }

            FNextElementLineToPrint[row.depth] = eStageElementPrinting.eFinished;
            return FPrinter.CurrentYPos;
        }
コード例 #20
0
ファイル: PrinterCommon.cs プロジェクト: Davincier/openpetra
 /// <summary>
 /// print the header for a normal level (not deepest level)
 /// </summary>
 /// <param name="row"></param>
 /// <returns></returns>
 protected virtual Boolean PrintNormalLevelHeader(TResult row)
 {
     return false;
 }
コード例 #21
0
 /// <summary>
 /// copy constructor; creates a copy of the given object
 ///
 /// </summary>
 /// <returns>void</returns>
 public TResult(TResult copy)
 {
     Assign(copy);
 }