Pergunta

Nosso aplicativo WinForms há muito tempo permitiu uma opção "impressão" que basicamente usa o RDLC.

O cliente solicitou que adicionamos um recurso que permita que os usuários enviem a saída "impressa" por e -mail.

Agora, sabemos que um arquivo EMF é criado (na pasta Temp) como uma espécie de subproduto oculto do nosso processo de impressão atual.

Parece -nos que podemos simplesmente pegar esse arquivo EMF e anexá -lo a um novo email e o trabalho é feito.

  1. Esta é a melhor opção?
  2. Podemos confiar em um arquivo EMF ser aberto por qualquer máquina Windows?
  3. Como identificamos o arquivo EMF? ... apenas parece ser nomeado %TEMP%\DiaryGrid_1.emf atualmente. Ok, então o diarygrid é o nome do nosso arquivo RDLC, mas o _1 é adicionado em algum lugar ao longo do caminho.
Foi útil?

Solução

Eu fiz isso antes. Fiz isso exportando programaticamente o relatório para um PDF para um local específico, e enviamos por e -mail o arquivo PDF e o excluímos. Vou tentar encontrar o código para você (não em casa agora)

EDITADO:

Desculpe pelo mais tarde. Agora estou em casa e darei a você alguns blocos de código que acho que lhe darão ajuda para reclamar sua tarefa. Incluirei alguns comentários para o código para que você possa entender algumas coisas específicas no meu projeto. Esse código é testado e está funcionando bem em meus clientes, mas tenho certeza de que pode ser melhorado. Por favor, deixe -me saber se você pode melhorar este código;)

Primeiro de tudo, exportaremos o relatório para o 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;
}

Agora, precisamos de uma classe que controla o sistema de correio. Todo sistema de email tem suas próprias características, então talvez você precise modificar esta classe. O comportamento da classe é simples. Você só precisa preencher as propriedades e ligar para o método de envio. No meu caso, o Windows não me permita excluir o arquivo PDF depois de enviar (o Windows diz que o arquivo está em uso), então eu programo o arquivo a ser excluído na próxima reinicialização. Dê uma olhada no método de exclusão. Observe que o método de envio use uma classe Cutom chamada MailConfig. Esta é uma classe pequena que possui algumas seqüências de configuração, como host, nome de usuário e senha. O correio será enviado usando esses parâmetros.

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);
   }
}

Agora, você pode criar um formulário para solicitar os destinatários, adicionar alguma validação, etc., retornar a você uma instância da classe de email ... ou você pode simplesmente "codificar" os valores e preencher a classe.

Aqui está o código que eu uso em um botão para chamar este formulário, no meu exemplo, ele se chama 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();
}

Neste exemplo, SenmailView.CurrentItem é a instância da classe de email. Simplesmente precisamos ligar para o envio de Methis e o trabalho está realizado.

Esta é a maior resposta que eu já escrevi, então ... Espero que ajude: D Se você tiver algum problema em usá -la, me ligue. A propósito, não tenho muito orgulho do meu inglês, então me perdoe se o texto tiver algum erro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top