Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Exportar pagina de WebBrowser a PDF (https://www.clubdelphi.com/foros/showthread.php?t=96288)

pgranados 04-07-2023 20:34:48

Exportar pagina de WebBrowser a PDF
 
Buen día, busco exportar el contenido de un WebBrowser a un archivo PDF, tengo esta función pero el PDF que me descarga esta roto, directamente no abre (pero si tiene tamaño mayor a 0kb)

Código Delphi [-]
uses ActiveX;

function TForm1.PDF(Ruta:String):boolean;
var
  Stream : TFileStream;
  StreamAdapter: IStream;
  PersistStreamInit: IPersistStreamInit;

begin
 if not Assigned(Navegador.Document) then
  Exit;
 if Navegador.Document.QueryInterface(IPersistStreamInit, PersistStreamInit) = S_OK then
  begin
   Stream := TFileStream.Create(Ruta, fmCreate);
   try
    StreamAdapter := TStreamAdapter.Create(Stream);
    PersistStreamInit.Save(StreamAdapter, True);
   finally
    Stream.Free;
   end;
  end;
end;

A la función le paso la ruta destino del PDF, ¿alguna alternativa? Intenté con fastreport pero se ve feo porque la pagina también tiene CSS no solo HTML.

Saludos!

Casimiro Notevi 05-07-2023 10:03:48

¿Puede servir algo así?
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  RichEdit: TRichEdit;
  HTMLDocument: IHTMLDocument2;
  PrintRange: TFormatRange;
  PrinterHandle: HDC;
  FileName: string;
  FileStream: TFileStream;
begin
  RichEdit := TRichEdit.Create(Self);
  try
    RichEdit.Visible := False;
    RichEdit.Parent := Self; // Puedes ajustar esto según tu formulario o diseño.

    // Obtener el documento HTML del WebBrowser.
    HTMLDocument := (WebBrowser1.Document as IHTMLDocument2);

    // Copiar el contenido del documento HTML al RichEdit.
    RichEdit.PlainText := True;
    RichEdit.Lines.Text := HTMLDocument.body.innerHTML;

    // Imprimir el contenido del RichEdit en un archivo PDF.
    FileName := 'C:\ruta\archivo.pdf';
    FileStream := TFileStream.Create(FileName, fmCreate);
    try
      Printer.PrinterIndex := Printer.PrinterIndex; // Configurar la impresora actual.
      Printer.Title := FileName;
      Printer.BeginDoc;

      PrinterHandle := Printer.Canvas.Handle;
      FillChar(PrintRange, SizeOf(PrintRange), 0);
      PrintRange.hdc := PrinterHandle;
      PrintRange.hdcTarget := PrinterHandle;
      PrintRange.rc := Rect(0, 0,
        Printer.PageWidth * Printer.PixelsPerInch div 1440,
        Printer.PageHeight * Printer.PixelsPerInch div 1440);
      PrintRange.rcPage := PrintRange.rc;
      PrintRange.chrg.cpMax := -1;

      SendMessage(RichEdit.Handle, EM_FORMATRANGE, 1, Longint(@PrintRange));
      SendMessage(RichEdit.Handle, EM_FORMATRANGE, 0, 0);

      Printer.EndDoc;
    finally
      FileStream.Free;
    end;
  finally
    RichEdit.Free;
  end;
end;

pgranados 05-07-2023 17:15:43

Cita:

Empezado por Casimiro Notevi (Mensaje 551947)
¿Puede servir algo así?
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  RichEdit: TRichEdit;
  HTMLDocument: IHTMLDocument2;
  PrintRange: TFormatRange;
  PrinterHandle: HDC;
  FileName: string;
  FileStream: TFileStream;
begin
  RichEdit := TRichEdit.Create(Self);
  try
    RichEdit.Visible := False;
    RichEdit.Parent := Self; // Puedes ajustar esto según tu formulario o diseño.

    // Obtener el documento HTML del WebBrowser.
    HTMLDocument := (WebBrowser1.Document as IHTMLDocument2);

    // Copiar el contenido del documento HTML al RichEdit.
    RichEdit.PlainText := True;
    RichEdit.Lines.Text := HTMLDocument.body.innerHTML;

    // Imprimir el contenido del RichEdit en un archivo PDF.
    FileName := 'C:\ruta\archivo.pdf';
    FileStream := TFileStream.Create(FileName, fmCreate);
    try
      Printer.PrinterIndex := Printer.PrinterIndex; // Configurar la impresora actual.
      Printer.Title := FileName;
      Printer.BeginDoc;

      PrinterHandle := Printer.Canvas.Handle;
      FillChar(PrintRange, SizeOf(PrintRange), 0);
      PrintRange.hdc := PrinterHandle;
      PrintRange.hdcTarget := PrinterHandle;
      PrintRange.rc := Rect(0, 0,
        Printer.PageWidth * Printer.PixelsPerInch div 1440,
        Printer.PageHeight * Printer.PixelsPerInch div 1440);
      PrintRange.rcPage := PrintRange.rc;
      PrintRange.chrg.cpMax := -1;

      SendMessage(RichEdit.Handle, EM_FORMATRANGE, 1, Longint(@PrintRange));
      SendMessage(RichEdit.Handle, EM_FORMATRANGE, 0, 0);

      Printer.EndDoc;
    finally
      FileStream.Free;
    end;
  finally
    RichEdit.Free;
  end;
end;

Gracias por tu respuesta Casimiro, pero no me funciono en Delphi 10.4, de entrada no me reconoce la propiedad Printer.PixelsPerInch
Código Delphi [-]
PrintRange.rc := Rect(0, 0,
              Printer.PageWidth * Printer.PixelsPerInch div 1440,
              Printer.PageHeight * Printer.PixelsPerInch div 1440);

Modifique un poco el código que me diste y como quiera sigue sin cumplirse el objetivo, me imprime el html (codigo) en el documento.

¿Sabrás si hay otra forma de hacerlo? Saludos.

Casimiro Notevi 05-07-2023 17:22:53

¿Has añadido "printers" al "uses"?

pgranados 05-07-2023 17:23:40

Si, ¿el código te funciona a ti en Delphi 10,4?

Casimiro Notevi 05-07-2023 17:42:37

A mí me sale error porque no tengo impresora, no sé si realmente funcionará.
De todas formas cambia algunas cosas, por probar que no quede:


Código Delphi [-]
unit Unit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, printers,    RichEdit,
  Vcl.OleCtrls, SHDocVw,MSHTML;

type
  TForm4 = class(TForm)
    Button1: TButton;
    RichEdit1: TRichEdit;
    WebBrowser1: TWebBrowser;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.Button1Click(Sender: TObject);
var
  RichEdit: TRichEdit;
  HTMLDocument: IHTMLDocument2;
  PrintRange: TFormatRange;
  PrinterHandle: HDC;
  FileName: string;
  FileStream: TFileStream;
  DPI: Integer;

begin

PrinterHandle := Printer.Canvas.Handle;
 DPI := GetDeviceCaps(PrinterHandle, LOGPIXELSX);

  RichEdit := TRichEdit.Create(Self);
  try
    RichEdit.Visible := False;
    RichEdit.Parent := Self; // Puedes ajustar esto según tu formulario o diseño.

    // Obtener el documento HTML del WebBrowser.
    HTMLDocument := (WebBrowser1.Document as IHTMLDocument2);

    // Copiar el contenido del documento HTML al RichEdit.
    RichEdit.PlainText := True;
    RichEdit.Lines.Text := HTMLDocument.body.innerHTML;

    // Imprimir el contenido del RichEdit en un archivo PDF.
    FileName := 'C:\ruta\archivo.pdf';
    FileStream := TFileStream.Create(FileName, fmCreate);
    try
      Printer.PrinterIndex := Printer.PrinterIndex; // Configurar la impresora actual.
      Printer.Title := FileName;
      Printer.BeginDoc;

      PrinterHandle := Printer.Canvas.Handle;
      FillChar(PrintRange, SizeOf(PrintRange), 0);
      PrintRange.hdc := PrinterHandle;
      PrintRange.hdcTarget := PrinterHandle;
      PrintRange.rc := Rect(0, 0,
        Printer.PageWidth * DPI div 1440,
        Printer.PageHeight * DPI div 1440);
      PrintRange.rcPage := PrintRange.rc;
      PrintRange.chrg.cpMax := -1;

      SendMessage(RichEdit.Handle, EM_FORMATRANGE, 1, Longint(@PrintRange));
      SendMessage(RichEdit.Handle, EM_FORMATRANGE, 0, 0);

      Printer.EndDoc;
    finally
      FileStream.Free;
    end;
  finally
    RichEdit.Free;
  end;

pgranados 05-07-2023 18:31:40

Ahora regresa un PDF en blanco :confused:

La pagina que debo de imprimir es esta: https://siat.sat.gob.mx/app/qr/faces..._BIHE8804258H1

No se si a ti te regrese el pdf con el contenido

Casimiro Notevi 05-07-2023 18:46:44

A mí me dice: "Printer is not currently printing".
Supongo que será porque no tengo impresora.

Casimiro Notevi 05-07-2023 18:59:10

1 Archivos Adjunto(s)
Vale, parece que va por buen camino, he conseguido crear un pdf, aunque con el contenido "raro" :D

pgranados 05-07-2023 19:04:13

Cita:

Empezado por Casimiro Notevi (Mensaje 551961)
Vale, parece que va por buen camino, he conseguido crear un pdf, aunque con el contenido "raro" :D

Intente hacerlo con fastReport soltando un objeto tipo HTML e ingresando el código y el contenido se visualiza perfecto pero el requerimiento es que venga tal cual el sitio :confused:

No se como hacerlo porque el sitio contiene css y demas, vi que guardando el sitio en formato .MHTML si se mantiene todo en archivo, el tema es como imprimir ese MHTML


Casimiro Notevi 05-07-2023 19:36:12

Desconozco ese tema :(
Por probar, he preguntado al chatgpt y dice esto:
Código Delphi [-]
uses
  ShellAPI;

procedure TForm1.Button1Click(Sender: TObject);
var
  FileName: string;
begin
  // Ruta completa al archivo MHTML que deseas imprimir
  FileName := 'C:\ruta\al\archivo.mhtml';

  // Cargar el archivo MHTML en el TWebBrowser
  WebBrowser1.Navigate('file://' + FileName);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  OLECMDID_PRINT2: Integer;
  OLECMDEXECOPT_DONTPROMPTUSER: Integer;
begin
  // Constantes específicas para impresión en MHTML
  OLECMDID_PRINT2 := 6;
  OLECMDEXECOPT_DONTPROMPTUSER := 2;

  // Imprimir el contenido del TWebBrowser
  if WebBrowser1.OleObject.DocumentLoaded then
  begin
    WebBrowser1.OleObject.ExecWB(OLECMDID_PRINT2, OLECMDEXECOPT_DONTPROMPTUSER);
  end;
end;

pgranados 06-07-2023 01:32:38

Cita:

Empezado por Casimiro Notevi (Mensaje 551963)
Desconozco ese tema :(
Por probar, he preguntado al chatgpt y dice esto:
Código Delphi [-]
uses
  ShellAPI;

procedure TForm1.Button1Click(Sender: TObject);
var
  FileName: string;
begin
  // Ruta completa al archivo MHTML que deseas imprimir
  FileName := 'C:\ruta\al\archivo.mhtml';

  // Cargar el archivo MHTML en el TWebBrowser
  WebBrowser1.Navigate('file://' + FileName);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  OLECMDID_PRINT2: Integer;
  OLECMDEXECOPT_DONTPROMPTUSER: Integer;
begin
  // Constantes específicas para impresión en MHTML
  OLECMDID_PRINT2 := 6;
  OLECMDEXECOPT_DONTPROMPTUSER := 2;

  // Imprimir el contenido del TWebBrowser
  if WebBrowser1.OleObject.DocumentLoaded then
  begin
    WebBrowser1.OleObject.ExecWB(OLECMDID_PRINT2, OLECMDEXECOPT_DONTPROMPTUSER);
  end;
end;

Esto funciono de maravilla, aunque no se si sea posible ocultar el dialog de guardar archivo que se genera y que en el PDF no se imprima en el header y en el footer información del navegador

Gracias por tu aporte casimiro!

Casimiro Notevi 06-07-2023 08:58:26

Sí que se puede, tienes que configurarlo en el navegador.
Cada navegador tiene opción de elegir una impresora predeterminada y que no pregunte.
Claro, ahí tendrás que configurar el que usa cada usuario.

pgranados 06-07-2023 17:56:42

Cita:

Empezado por Casimiro Notevi (Mensaje 551968)
Sí que se puede, tienes que configurarlo en el navegador.
Cada navegador tiene opción de elegir una impresora predeterminada y que no pregunte.
Claro, ahí tendrás que configurar el que usa cada usuario.

Listo, lo logre gracias a este programita: https://wkhtmltopdf.org/

Solamente hay que incluir la dll y el exe y mandarlo a llamar desde el cmd, seria algo así: wkhtmltopdf http://google.com google.pdf

Gracias por tu tiempo Casimiro

Casimiro Notevi 06-07-2023 18:37:23

^\||/^\||/^\||/


La franja horaria es GMT +2. Ahora son las 16:34:55.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi