Распространение выходных данных RDLC в качестве вложения электронной почты

В нашем приложении winforms уже давно разрешена опция «печать», которая в основном использует RDLC.

Клиент запросил, чтобы мы добавили функцию, позволяющую пользователям отправлять «распечатанный» вывод по электронной почте.

Теперь мы знаем, что файл EMF создается (в папке TEMP) как своего рода скрытый побочный продукт нашего текущего процесса печати.

Нам кажется, что мы можем просто взять этот EMF-файл и прикрепить его к новому электронному письму, и работа будет выполнена.

  1. Это лучший вариант?
  2. Можем ли мы полагаться на то, что файл EMF будет открыт на любом компьютере с Windows?
  3. Как мы идентифицируем файл EMF? ... в настоящее время кажется, что его зовут %TEMP%\DiaryGrid_1.emf. Итак, DiaryGrid — это имя нашего файла RDLC, но где-то по пути добавляется _1.

person hawbsl    schedule 03.10.2010    source источник


Ответы (1)


Я сделал это раньше. Я сделал это, программно экспортировав отчет в PDF-файл в определенное место, затем мы отправили PDF-файл по электронной почте и удалили его. Я постараюсь найти код для вас (сейчас не дома)

ОТРЕДАКТИРОВАНО:

Извините за позднее. Сейчас я дома, и я дам вам несколько блоков кода, которые, я думаю, помогут вам выполнить вашу задачу. Я добавлю некоторые комментарии к коду, чтобы вы могли понять некоторые особенности моего проекта. Этот код протестирован и хорошо работает в моих клиентах, но я уверен, что его можно улучшить. Пожалуйста, дайте мне знать, если вы можете улучшить этот код;)

Первым делом экспортируем отчет в pdf.

private string ExportReportToPDF(string reportName)
{
   Warning[] warnings;
   string[] streamids;
   string mimeType;
   string encoding;
   string filenameExtension;
   byte[] bytes = ReportViewer1.LocalReport.Render(
      "PDF", null, out mimeType, out encoding, out filenameExtension,
       out streamids, out warnings);

   string filename = Path.Combine(Path.GetTempPath(), reportName);
   using (var fs = new FileStream(filename, FileMode.Create))
   {
      fs.Write(bytes, 0, bytes.Length);
      fs.Close();
   }

   return filename;
}

Теперь нам нужен класс, управляющий почтовой системой. Каждая почтовая система имеет свои характеристики, поэтому, возможно, вам потребуется изменить этот класс. Поведение класса простое. Вам нужно только заполнить свойства и вызвать метод Send. В моем случае Windows не позволяет мне удалить файл PDF после его отправки (Windows сообщает, что файл используется), поэтому я программирую удаление файла при следующей перезагрузке. Обратите внимание на метод удаления. Обратите внимание, что метод отправки использует класс cutom с именем MailConfig. Это небольшой класс с некоторыми строками конфигурации, такими как хост, имя пользователя и пароль. Почта будет отправлена ​​с использованием этих параметров.

public class Mail
{
   public string Title { get; set; }
   public string Text { get; set; }
   public string From { get; set; }
   public bool RequireAutentication { get; set; }
   public bool DeleteFilesAfterSend { get; set; }

   public List<string> To { get; set; }
   public List<string> Cc { get; set; }
   public List<string> Bcc { get; set; }
   public List<string> AttachmentFiles { get; set; }

   #region appi declarations

   internal enum MoveFileFlags
   {
      MOVEFILE_REPLACE_EXISTING = 1,
      MOVEFILE_COPY_ALLOWED = 2,
      MOVEFILE_DELAY_UNTIL_REBOOT = 4,
      MOVEFILE_WRITE_THROUGH = 8
   }

   [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
   static extern bool MoveFileEx(string lpExistingFileName,
                                 string lpNewFileName,
                                 MoveFileFlags dwFlags);

   #endregion

   public Mail()
   {
      To = new List<string>();
      Cc = new List<string>();
      Bcc = new List<string>();
      AttachmentFiles = new List<string>();
      From = MailConfig.Username;
   }

   public void Send()
   {
      var client = new SmtpClient
      {
         Host = MailConfig.Host,
         EnableSsl = false,
      };

      if (RequireAutentication)
      {
         var credentials = new NetworkCredential(MailConfig.Username, 
                                                 MailConfig.Password);
         client.Credentials = credentials;
      }

      var message = new MailMessage
      {
         Sender = new MailAddress(From, From),
         From = new MailAddress(From, From)
      };

      AddDestinataryToList(To, message.To);
      AddDestinataryToList(Cc, message.CC);
      AddDestinataryToList(Bcc, message.Bcc);

      message.Subject = Title;
      message.Body = Text;
      message.IsBodyHtml = false;
      message.Priority = MailPriority.High;

      var attachments = AttachmentFiles.Select(file => new Attachment(file));
      foreach (var attachment in attachments)
         message.Attachments.Add(attachment);

      client.Send(message);

      if (DeleteFilesAfterSend)
         AttachmentFiles.ForEach(DeleteFile);
   }

   private void AddDestinataryToList(IEnumerable<string> from,
      ICollection<MailAddress> mailAddressCollection)
   {
      foreach (var destinatary in from)
         mailAddressCollection.Add(new MailAddress(destinatary, destinatary));
   }

   private void DeleteFile(string filepath)
   {
      // this should delete the file in the next reboot, not now.
      MoveFileEx(filepath, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
   }
}

Теперь вы можете создать форму для запроса адресатов, добавить некоторую проверку и т. д., вернуть вам экземпляр класса Mail... или вы можете просто "жестко закодировать" значения и заполнить класс.

Вот код, который я использую в кнопке для вызова этой формы, в моем примере она называется SendMailView.

private void BtnSendByMail_Click(object sender, EventArgs e)
{
   SendMailView sendMailView = new SendMailView();

   if (sendMailView.ShowDialog()== DialogResult.OK)
   {
      Mail mail = sendMailView.CurrentItem;
      mail.AttachmentFiles.Add(ExportReportToPDF("Invoice.pdf"));
      mail.DeleteFilesAfterSend = true;
      mail.RequireAutentication = true;
      mail.Send();
   }
   sendMailView.Dispose();
}

В этом примере senMailView.CurrentItem является экземпляром почтового класса. Нам просто нужно позвонить в Send methis, и работа сделана.

Это самый большой ответ, который я когда-либо писал в SO ... Надеюсь, он вам поможет: D Если у вас возникнут проблемы с его использованием, позвоните мне. Кстати, я не очень горжусь своим английским, так что простите меня, если в тексте есть ошибки.

person Jonathan    schedule 03.10.2010
comment
Удачи: D Дайте мне знать, если у вас есть какие-либо проблемы или вопросы. - person Jonathan; 31.10.2010