/// <summary>
        /// dump unmatched gifts or other transactions to a HTML table for printing
        /// </summary>
        private static string PrintHTML(
            AEpStatementRow ACurrentStatement,
            DataView AEpTransactions, AEpMatchTable AMatches, string ATitle,
            string ALetterTemplateFilename)
        {
            if ((ALetterTemplateFilename.Length == 0) || !File.Exists(ALetterTemplateFilename))
            {
                OpenFileDialog DialogOpen = new OpenFileDialog();
                DialogOpen.Filter = "Report template (*.html)|*.html";
                DialogOpen.RestoreDirectory = true;
                DialogOpen.Title = "Open Report Template";

                if (DialogOpen.ShowDialog() == DialogResult.OK)
                {
                    ALetterTemplateFilename = DialogOpen.FileName;
                }
            }

            // message body from HTML template
            StreamReader reader = new StreamReader(ALetterTemplateFilename);
            string msg = reader.ReadToEnd();

            reader.Close();

            msg = msg.Replace("#TITLE", ATitle);
            msg = msg.Replace("#PRINTDATE", DateTime.Now.ToShortDateString());

            if (!ACurrentStatement.IsIdFromBankNull())
            {
                msg = msg.Replace("#STATEMENTNR", ACurrentStatement.IdFromBank);
            }

            if (!ACurrentStatement.IsStartBalanceNull())
            {
                msg = msg.Replace("#STARTBALANCE", String.Format("{0:N}", ACurrentStatement.StartBalance));
            }

            if (!ACurrentStatement.IsEndBalanceNull())
            {
                msg = msg.Replace("#ENDBALANCE", String.Format("{0:N}", ACurrentStatement.EndBalance));
            }

            // recognise detail lines automatically
            string RowTemplate;
            msg = TPrinterHtml.GetTableRow(msg, "#NRONSTATEMENT", out RowTemplate);
            string rowTexts = "";

            BankImportTDSAEpTransactionRow row = null;

            AEpTransactions.Sort = BankImportTDSAEpTransactionTable.GetNumberOnPaperStatementDBName();

            Decimal Sum = 0.0m;
            Int32 NumberPrinted = 0;

            DataView MatchesByMatchText = new DataView(AMatches,
                string.Empty,
                AEpMatchTable.GetMatchTextDBName(),
                DataViewRowState.CurrentRows);

            string thinLine = "<font size=\"-3\">-------------------------------------------------------------------------<br/></font>";

            foreach (DataRowView rv in AEpTransactions)
            {
                row = (BankImportTDSAEpTransactionRow)rv.Row;

                string rowToPrint = RowTemplate;

                // short description, remove all SEPA stuff
                string ShortDescription = RemoveSEPAText(row.Description);

                rowToPrint = rowToPrint.Replace("#NAME", row.AccountName);
                rowToPrint = rowToPrint.Replace("#DESCRIPTION", row.Description);
                rowToPrint = rowToPrint.Replace("#SHORTDESCRIPTION", ShortDescription);

                string RecipientDescription = string.Empty;

                DataRowView[] matches = MatchesByMatchText.FindRows(row.MatchText);

                AEpMatchRow match = null;

                foreach (DataRowView rvMatch in matches)
                {
                    match = (AEpMatchRow)rvMatch.Row;

                    if (RecipientDescription.Length > 0)
                    {
                        RecipientDescription += "<br/>";
                    }

                    if (!match.IsRecipientKeyNull() && (match.RecipientKey > 0))
                    {
                        RecipientDescription += match.RecipientKey.ToString() + " ";
                    }

                    RecipientDescription += match.RecipientShortName;
                }

                if (RecipientDescription.Trim().Length > 0)
                {
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTIONUNMATCHED", string.Empty);
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTION", "<br/>" + thinLine + RecipientDescription);
                }
                else
                {
                    // extra space for unmatched gifts
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTIONUNMATCHED", "<br/><br/>");
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTION", string.Empty);
                }

                if ((match != null) && !match.IsDonorKeyNull() && (match.DonorKey > 0))
                {
                    string DonorDescription = "<br/>" + thinLine + match.DonorKey.ToString() + " " + match.DonorShortName;

                    rowToPrint = rowToPrint.Replace("#DONORDESCRIPTION", DonorDescription);
                    rowToPrint = rowToPrint.Replace("#DONORKEY", StringHelper.PartnerKeyToStr(match.DonorKey));
                    rowToPrint = rowToPrint.Replace("#DONORNAMEORDESCRIPTION", match.DonorShortName);
                }
                else
                {
                    rowToPrint = rowToPrint.Replace("#DONORDESCRIPTION", string.Empty);
                    rowToPrint = rowToPrint.Replace("#DONORKEY", string.Empty);
                    rowToPrint = rowToPrint.Replace("#DONORNAMEORDESCRIPTION", row.AccountName);
                }

                rowTexts += rowToPrint.
                            Replace("#NRONSTATEMENT", row.NumberOnPaperStatement.ToString()).
                            Replace("#AMOUNT", String.Format("{0:C}", row.TransactionAmount)).
                            Replace("#IBANANDBIC",
                    row.IsIbanNull() ? string.Empty : "<br/>" + row.Iban + "<br/>" + row.Bic).
                            Replace("#IBAN", row.Iban).
                            Replace("#BIC", row.Bic).
                            Replace("#ACCOUNTNUMBER", row.BankAccountNumber).
                            Replace("#BANKSORTCODE", row.BranchCode);

                Sum += Convert.ToDecimal(row.TransactionAmount);
                NumberPrinted++;
            }

            Sum = Math.Round(Sum, 2);

            msg = msg.Replace("#ROWTEMPLATE", rowTexts);
            msg = msg.Replace("#TOTALAMOUNT", String.Format("{0:C}", Sum));
            msg = msg.Replace("#TOTALNUMBER", NumberPrinted.ToString());

            return msg;
        }