Domanda

La nostra WinForms applicazione ha permesso a lungo un'opzione "stampa", che utilizza fondamentalmente RDLC.

Il cliente ha richiesto che si aggiunge una funzione che permette agli utenti di inviare l'output "stampato" via e-mail.

Ora, sappiamo che viene creato un file EMF (nella cartella TEMP) come una sorta di sottoprodotto nascosta del nostro processo di stampa in corso.

A noi sembra che possiamo semplicemente prendere questo file EMF e allegarlo a un nuovo messaggio e il gioco è fatto.

  1. E 'questo l'opzione migliore?
  2. Possiamo contare su un file EMF essere aperto da qualsiasi macchina Windows?
  3. Come identificare il file EMF? ... sembra proprio di essere chiamato %TEMP%\DiaryGrid_1.emf al momento. OK così DiaryGrid è il nome del nostro file RDLC ma il _1 ottiene da qualche parte lungo la strada aggiunto.
È stato utile?

Soluzione

L'ho fatto prima. L'ho fatto esportazione programatically il rapporto in un pdf in una posizione specifica, poi inviare il file pdf ed eliminarlo. Cercherò di trovare il codice per voi (Non in casa ora)

Modificato:

Ci scusiamo per la successiva. Ora sono in casa e io vi darò alcuni blocchi di codice che penso che vi darà un aiuto per compire il vostro compito. I comprenderà alcuni commenti al codice in modo da poter capire alcune cose che sono specifiche nel mio progetto. Questo codice sono testati e stanno lavorando bene in miei clienti, ma sono sicuro che può essere migliorato. Ti prego, fammi sapere se è possibile migliorare questo codice;)

Prima di tutto, ci sarà esportare il report in 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;
}

Ora, abbiamo bisogno di una classe che controlla il sistema di posta elettronica. Ogni sistema di posta elettronica ha le proprie tipo, così forse avrete bisogno di modificare questa classe. Il comportamento della classe è semplice. Hai solo bisogno di riempire le proprietà, e chiamare il metodo Send. Nel mio caso, le finestre non mi permette di cancellare il file pdf, una volta lo invio (Windows dice che il file è in uso), quindi programmare il file da cancellare nel prossimo riavvio. Date un'occhiata al metodo di eliminazione. Prega di notare che il metodo Send utilizzare una classe di nome cutom MailConfig. Si tratta di una piccola classe che ha alcune stringhe di configurazione come host, Nome utente e Password. La posta sarà inviata utilizzando questa params.

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

Ora, è possibile creare un modulo per richiedere le destinataries, aggiungere un po 'di validazione, ecc, di ritorno a voi un'istanza della classe Mail ... oppure si può semplicemente "codificare" i valori e riempire la classe.

Ecco il codice che uso in un pulsante per chiamare questa forma, nel mio esempio è chiamato 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();
}

In questo esempio senMailView.CurrentItem è l'istanza della classe di posta. Abbiamo semplicemente bisogno di chiamare per le Methis di invio e il lavoro è fatto.

Questa è la risposta più grande che io abbia mai scritto in SO ... Spero che ti aiuta: D Se avete qualche problema ad usarlo, mi chiamano. Tra l'altro, io non sono molto orgoglioso del mio inglese, quindi perdonatemi se il testo ha qualche errore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top