2010-01-25 22 views
5

J'utilise abcPdf pour convertir un rapport HTML en fichier pdf. Le pdf doit être une page A4 paysage unique. Savez-vous s'il existe un moyen de dire à abcPdf d'adapter la page HTML pour l'adapter à une seule page dans le fichier pdf? J'ai essayé d'utiliser le Magnify() method, et il met à l'échelle le contenu, mais le divise toujours en pages, même si cela pourrait tenir sur une page. Je me suis gratté la tête depuis un moment et je me demande si quelqu'un l'a fait.Dites à abcPdf de mettre à l'échelle le html pour l'adapter à une seule page pdf

Voici le code que je utilise au moment:

public byte[] UrlToPdf(string url, PageOrientation po) 
{ 
    using (Doc theDoc = new Doc()) 
    { 
     // When in landscape mode: 
     // We use two transforms to apply a generic 90 degree rotation around 
     // the center of the document and rotate the drawing rectangle by the same amount. 
     if (po == PageOrientation.Landscape) 
     { 
      // apply a rotation transform 
      double w = theDoc.MediaBox.Width; 
      double h = theDoc.MediaBox.Height; 
      double l = theDoc.MediaBox.Left; 
      double b = theDoc.MediaBox.Bottom; 
      theDoc.Transform.Rotate(90, l, b); 
      theDoc.Transform.Translate(w, 0); 

      // rotate our rectangle 
      theDoc.Rect.Width = h; 
      theDoc.Rect.Height = w; 

      // To change the default orientation of the document we need to apply a rotation to the root page object. 
      //By doing this we ensure that every page in the document is viewed rotated. 
      int theDocID = Convert.ToInt32(theDoc.GetInfo(theDoc.Root, "Pages")); 
      theDoc.SetInfo(theDocID, "/Rotate", "90"); 
     } 

     theDoc.HtmlOptions.PageCacheEnabled = false; 
     theDoc.HtmlOptions.AddForms = false; 
     theDoc.HtmlOptions.AddLinks = false; 
     theDoc.HtmlOptions.AddMovies = false; 
     theDoc.HtmlOptions.FontEmbed = false; 
     theDoc.HtmlOptions.UseResync = false; 
     theDoc.HtmlOptions.UseVideo = false; 
     theDoc.HtmlOptions.UseScript = false; 
     theDoc.HtmlOptions.HideBackground = false; 
     theDoc.HtmlOptions.Timeout = 60000; 
     theDoc.HtmlOptions.BrowserWidth = 0; 
     theDoc.HtmlOptions.ImageQuality = 101; 

     // Add url to document. 
     int theID = theDoc.AddImageUrl(url, true, 0, true); 
     while (true) 
     { 
      if (!theDoc.Chainable(theID)) 
       break; 
      theDoc.Page = theDoc.AddPage(); 
      theID = theDoc.AddImageToChain(theID); 
     } 
     //Flattening the pages (Whatever that means) 
     for (int i = 1; i <= theDoc.PageCount; i++) 
     { 
      theDoc.PageNumber = i; 
      theDoc.Flatten(); 
     } 

     return theDoc.GetData(); 
    } 
} 

Répondre

5

est donc ici comment je résolu ce problème.

D'abord, je devais la hauteur de la page HTML à passer à la méthode de production pdf, donc j'ajouté sur la page à pdf-ed:

<asp:HiddenField ID="hfHeight" runat="server" /> 

et dans le code derrière :

protected void Page_Init(object sender, EventArgs e) 
{ 
    if (!IsPostBack) 
    { 
     string scriptKey = "WidhtHeightForPdf"; 
     if (!Page.ClientScript.IsClientScriptBlockRegistered(scriptKey)) 
     { 
      StringBuilder sb = new StringBuilder(); 
      sb.AppendLine("<script>") 
       .AppendLine("document.getElementById('" + hfHeight.ClientID + "').value = document.body.clientHeight;") 
       .AppendLine("</script>"); 

      Page.ClientScript.RegisterStartupScript(typeof(Page), scriptKey, sb.ToString()); 
     } 
    } 
} 

Maintenant, quand j'appelle la méthode de génération de pdf je peux lui passer la taille du HTML. Une fois que je la hauteur, il est une question de calcul de la largeur du pdf « fenêtre » de telle sorte que la hauteur correspond à la page pdf:

int intHTMLWidth = height.Value * Convert.ToInt32(theDoc.Rect.Width/theDoc.Rect.Height); 

Et puis spécifiez le paramètre BrowserWidth soit par HtmlOptions de theDoc:

theDoc.HtmlOptions.BrowserWidth = intHTMLWidth; 

ou lors de l'ajout de l'URL à theDoc:

EDIT: Cela résout la question, alors je vais pour le marquer comme une réponse. Maintenant, la prochaine chose à faire est de créer le pdf en mode protrait ou en mode paysage en fonction de la largeur et de la hauteur du HTML, de sorte que l'espace maximum soit utilisé sur la page pdf.

+0

Avez-vous terminé cela et que tout fonctionne? –

+0

Salut mike ou beon quelqu'un a idée sur le problème ci-dessous http://stackoverflow.com/questions/22069825/abcpdf-not-showing-full-table-data – SivaRajini

1

Cela pourrait être un peu plus simple

/// <summary> 
    /// Calculate the height of given html 
    /// </summary> 
    /// <param name="html"></param> 
    /// <returns></returns> 
    public int CalculateHeight(string html) 
    { 
     int id = _Document.AddImageHtml(html); 
     int height = (int)(_Document.GetInfoInt(id, "ScrollHeight") * PixelToPointScale); 
     _Document.Delete(id); 
     return height; 
    } 

[modifier] bien scrollHeight échoue avec ver8 cela fonctionne bien

private int AddImageHtml(string html) 
    { 
     try 
     { 
      return _Document.AddImageHtml("<div id='pdfx-div-pdf-frame' class='abcpdf-tag-visible' style='abcpdf-tag-visible: true; border: 1px solid red'>" + html + "</div>"); 
     } 
     catch (Exception ex) 
     { 
      throw new Exception(html, ex); 
     } 
    } 

    private double GetElementHeight(int id) 
    { 
     abcpdf.XRect[] tagRects = _Document.HtmlOptions.GetTagRects(id); 
     string[] tagIds = _Document.HtmlOptions.GetTagIDs(id); 

     for (int i=0;i<tagRects.Length;i++) 
     { 
      abcpdf.XRect rect = tagRects[i]; 
      string tagId = tagIds[i]; 
      if (string.Equals(tagId, "pdfx-div-pdf-frame", StringComparison.CurrentCultureIgnoreCase)) 
      { 
       return rect.Height; 
      } 
     } 
     return -1; 
    } 
0

Si vous utilisez le moteur 'Gecko', ce moteur ne support 'GetInfoInt' nous avons donc besoin d'écrire du javascript pour obtenir la hauteur. Faites un rendu fictif en premier pour déterminer la hauteur, puis définissez cette hauteur sur AbcDoc d'origine.

using (var tempDoc = new Doc()) 
       { 
        tempDoc.HtmlOptions.Engine = EngineType.Gecko; 
        tempDoc.HtmlOptions.Media = MediaType.Print; 
        tempDoc.HtmlOptions.UseScript = true; 
        if (width.HasValue) 
         tempDoc.HtmlOptions.BrowserWidth = width.Value; 

        tempDoc.HtmlOptions.OnLoadScript = " window.onbeforeprint = function() { document.documentElement.abcpdf = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);}"; 
        int theTempID = tempDoc.AddImageHtml(htmlData); 

        int height = Convert.ToInt32(tempDoc.HtmlOptions.GetScriptReturn(theTempID)); 

        tempDoc.Clear(); 
        tempDoc.Dispose(); 

        theDoc.MediaBox.Height = height; 
        theDoc.Rect.String = theDoc.MediaBox.String; 
        theDoc.AddImageHtml(htmlData); 
       }