web-dev-qa-db-fra.com

iTextSharp Remplacer le texte dans existant PDF sans perdre la formation

Je cherche Internet depuis 2 semaines et j'ai trouvé des solutions intéressantes à mon problème, mais rien ne semble me donner la réponse.

Mon but est de faire ce qui suit:

Je veux trouver un texte dans un fichier PDF statique et remplacer ce texte par un autre texte. J'aimerais conserver la conception du contenu. Est-ce vraiment si difficile?

J'ai trouvé un moyen mais j'ai perdu toute l'information:

 using (PdfReader reader = new PdfReader(path))
        {

            StringBuilder text = new StringBuilder();
            for (int i = 1; i <= reader.NumberOfPages; i++)
            {
                text.Append(PdfTextExtractor.GetTextFromPage(reader, i));
                text.Replace(txt_SuchenNach.Text, txt_ErsetzenMit.Text);
            }

            return text.ToString();
        }

Le deuxième essai que j’avais était bien meilleur, mais il me fallait des champs dans lesquels je peux changer le texte:

 string fileNameExisting =path;
        string fileNameNew = @"C:\TEST.pdf";

        using (FileStream existingFileStream = new FileStream(fileNameExisting, FileMode.Open))
        using (FileStream newFileStream = new FileStream(fileNameNew, FileMode.Create))
        {
            // PDF öffnen
            PdfReader pdfReader = new PdfReader(existingFileStream);


            PdfStamper stamper = new PdfStamper(pdfReader, newFileStream);

            var form = stamper.AcroFields;
            var fieldKeys = form.Fields.Keys;
            foreach (string fieldKey in fieldKeys)
            {                    
                var value = pdfReader.AcroFields.GetField(fieldKey);
                form.SetField(fieldKey, value.Replace(txt_SuchenNach.Text, txt_ErsetzenMit.Text));
            }

            // Textfeld unbearbeitbar machen (sieht aus wie normaler text)
            stamper.FormFlattening = true;

            stamper.Close();
            pdfReader.Close();
        }

Cela conserve la mise en forme du reste du texte et ne modifie que le texte recherché. J'ai besoin d'une solution pour le texte qui n'est pas dans un champ de texte.

merci pour toutes vos réponses et votre aide.

7
Kevin Plaul

Le problème général est que les objets texte peuvent utiliser des polices incorporées avec des glyphes spécifiques affectés à des lettres spécifiques. C'est à dire. Si vous avez un objet texte avec du texte tel que "abcdef", la police incorporée peut contenir des glyphes uniquement pour ces lettres ("abcdef"), mais pas pour d'autres lettres. Donc, si vous remplacez "abcdef" par "xyz", le PDF n'affichera pas ces "xyz", car aucun glyphe n'est disponible pour l'affichage de ces lettres.

Je considérerais donc le flux de travail suivant:

  • Parcourez tous les objets texte;
  • Ajoute de nouveaux objets texte créés de toutes pièces sur le fichier PDF et définisse les mêmes propriétés (police, position, etc.) mais avec un texte différent; Cette étape peut nécessiter que vous installiez les mêmes polices que celles utilisées dans le fichier PDF d'origine _, mais vous pouvez rechercher les polices installées et utiliser une autre police pour un nouvel objet texte. De cette manière, iTextSharp ou un autre outil PDF incorporera un nouvel objet de police pour un nouvel objet de texte.
  • Supprimez l'objet texte d'origine une fois que vous avez créé un objet texte dupliqué.
  • Traitez chaque objet texte avec le workflow décrit ci-dessus;
  • Enregistrez le document PDF modifié dans un nouveau fichier.
4
Eugene

J'ai travaillé sur la même exigence et je peux y parvenir en suivant les étapes suivantes.

Étape 1: Localisation du fichier PDF source et du chemin du fichier de destination

Étape 2: Lire le fichier PDF source et rechercher l’emplacement de la chaîne à remplacer

Étape 3: Remplacement de la chaîne par une nouvelle. 

using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using PDFExtraction;    
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace PDFReplaceTextUsingItextSharp
{
    public partial class ExtractPdf : System.Web.UI.Page
    {
        static iTextSharp.text.pdf.PdfStamper stamper = null;
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Replace_Click(object sender, EventArgs e)
        {
            string ReplacingVariable = txtReplace.Text; 
            string sourceFile = "Source File Path";
            string descFile = "Destination File Path";
            PdfReader pReader = new PdfReader(sourceFile);
            stamper = new iTextSharp.text.pdf.PdfStamper(pReader, new System.IO.FileStream(descFile, System.IO.FileMode.Create));
            PDFTextGetter("ExistingVariableinPDF", ReplacingVariable , StringComparison.CurrentCultureIgnoreCase, sourceFile, descFile);
            stamper.Close();
            pReader.Close();
        }


        /// <summary>
        /// This method is used to search for the location words in pdf and update it with the words given from replacingText variable
        /// </summary>
        /// <param name="pSearch">Searchable String</param>
        /// <param name="replacingText">Replacing String</param>
        /// <param name="SC">Case Ignorance</param>
        /// <param name="SourceFile">Path of the source file</param>
        /// <param name="DestinationFile">Path of the destination file</param>
        public static void PDFTextGetter(string pSearch, string replacingText, StringComparison SC, string SourceFile, string DestinationFile)
        {
            try
            {
                iTextSharp.text.pdf.PdfContentByte cb = null;
                iTextSharp.text.pdf.PdfContentByte cb2 = null;
                iTextSharp.text.pdf.PdfWriter writer = null;
                iTextSharp.text.pdf.BaseFont bf = null;

                if (System.IO.File.Exists(SourceFile))
                {
                    PdfReader pReader = new PdfReader(SourceFile);


                    for (int page = 1; page <= pReader.NumberOfPages; page++)
                    {
                        myLocationTextExtractionStrategy strategy = new myLocationTextExtractionStrategy();
                        cb = stamper.GetOverContent(page);
                        cb2 = stamper.GetOverContent(page);

                        //Send some data contained in PdfContentByte, looks like the first is always cero for me and the second 100, 
                        //but i'm not sure if this could change in some cases
                        strategy.UndercontentCharacterSpacing = (int)cb.CharacterSpacing;
                        strategy.UndercontentHorizontalScaling = (int)cb.HorizontalScaling;

                        //It's not really needed to get the text back, but we have to call this line ALWAYS, 
                        //because it triggers the process that will get all chunks from PDF into our strategy Object
                        string currentText = PdfTextExtractor.GetTextFromPage(pReader, page, strategy);

                        //The real getter process starts in the following line
                        List<iTextSharp.text.Rectangle> MatchesFound = strategy.GetTextLocations(pSearch, SC);

                        //Set the fill color of the shapes, I don't use a border because it would make the rect bigger
                        //but maybe using a thin border could be a solution if you see the currect rect is not big enough to cover all the text it should cover
                        cb.SetColorFill(BaseColor.WHITE);

                        //MatchesFound contains all text with locations, so do whatever you want with it, this highlights them using PINK color:

                        foreach (iTextSharp.text.Rectangle rect in MatchesFound)
                        {
                            //width
                            cb.Rectangle(rect.Left, rect.Bottom, 60, rect.Height);
                            cb.Fill();
                            cb2.SetColorFill(BaseColor.BLACK);
                            bf = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);

                            cb2.SetFontAndSize(bf, 9);

                            cb2.BeginText();
                            cb2.ShowTextAligned(0, replacingText, rect.Left, rect.Bottom, 0);   
                            cb2.EndText();
                            cb2.Fill();
                        }

                    }
                }

            }
            catch (Exception ex)
            {

            }

        }

    }
}
1
Pradeep Kumar