Распространение вывода RDLC в виде вложения электронной почты - PullRequest
5 голосов
/ 03 октября 2010

Наше приложение winforms долго разрешало опцию "print", которая в основном использует RDLC.

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

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

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

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

1 Ответ

8 голосов
/ 03 октября 2010

Я делал это раньше.Я сделал это, экспортируя отчет программно в файл 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 говорит, что файл используется), поэтому я запрограммировал файл для удаления при следующей перезагрузке.Посмотрите на метод удаления.Обратите внимание, что метод send использует класс cutom с именем MailConfig.Это небольшой класс, который имеет несколько строк конфигурации, таких как Host, User Name и Password.Письмо будет отправлено с использованием этих параметров.

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 является экземпляром класса mail.Нам просто нужно позвонить в «Отправить метис» и работа сделана.

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

...