1

PDFからデータを抽出するためにiTextSharpを使用しています。以下のシナリオで示されている次の問題に出くわしました。

説明のためにサンプルの Excel ファイルを作成しました。これは次のようになります。 ここに画像の説明を入力

そこにある多くの無料のオンラインコンバーターの1つを使用して、それをpdfに変換します。これにより、次のようなpdfが生成されます(pdfを生成したときに、スタイルをExcelに適用しませんでした)。 ここに画像の説明を入力

ここでiTextSharp、pdf からデータを抽出するために使用すると、抽出されたデータとして次の文字列が返されます。

ここに画像の説明を入力

ご覧のとおり、ラップされたセル データは新しい行を生成し、ラップされたデータの各部分は 1 つの空白で区切られます。

問題:ラップされたデータの特定の部分がどの列に属しているかをどのように識別するのですか? iTextSharp列と同じ数の空白のみを保持する場合...

私の例では、 111がどの列に属しているかをどのように特定できますか?


更新 1:

フィールドに複数の単語が含まれる (つまり、空白が含まれる) 場合は常に、同様の問題が発生します。たとえば、上記のサンプルの 1 行目を考えてみます。

似ていたと言う

---A---  ---B---  ---C---  ---D---
aaaaaaa    bb b     cccc      

iText はこの場合も、次のように抽出を生成します。

aaaaaaa bb b cccc

ここでも同じ問題があり、各列の境界を決定する必要があります。


更新 2: 私が使用している実際の pdf ファイルのサンプル: ここに画像の説明を入力 これは、pdf データがどのように見えるかです。

4

3 に答える 3

5

これは本当の答えではありませんが、物事を理解するのに役立つかもしれないいくつかのことを示す場所が必要でした.

Excel、Word、PowerPoint、HTML などから PDF への最初の「変換」は、ほとんどの場合、破壊的な変更になります。破壊的な部分は非常に重要であり、そのデータが何を表すかについて非常に具体的な知識を持つプログラム (Excel) からデータを取得し、それを非常に一般的なユニバーサル形式 (PDF) のみを気にする描画コマンドに変換するために発生します。データ自体ではなく、データがどのように見えるかについて。データが「タグ付け」されていない限り (そして最近ではほとんどタグ付けされていません) 、描画コマンドのコンテキストはありません。段落も、文x,yも、列も、行も、表もありません。でこの単語を描きa,bます。

次に、Excel ファイルに次のデータがあり、何らかの理由で、PDF が作成されたときに最後の列が他の列よりも狭かったとします。

Column A | Column B | Column 
                      C
Data #1    Data #2    Data
                      #3

あなたと私には文脈があるので、2 行目と 4目は実際には 1 行目と 3行目の続きであることがわかります。しかし、iText は抽出中にコンテキストを持たないため、そのようには考えず、4 行のテキストが表示されます。実際には、コンテキストがないため、も表示されず、行自体のみが表示されます。

3 番目に、非常に小さなことですが、PDFではスペースを描画しないことを理解する必要があります。以下の 3 列のテーブルを想像してください。

Column A | Column B | Column C
                      Yes

PDF からそれを抽出すると、次のデータが得られます。

Column A | Column B | Column C
Yes

PDF内では、「はい」という単語はx、あなたと私が3番目の列の下にあると考える特定の座標に描画され、その前にたくさんのスペースがありません.

冒頭で述べたように、これは大した答えではありませんが、解決しようとしている問題について説明できることを願っています。PDF がタグ付けされている場合、コンテキストがあり、抽出中にそのコンテキストを使用できます。ただし、コンテキストは普遍的ではないため、通常、魔法のような「コンテキストを挿入」チェックボックスはありません。Excelには、エクスポート中にタグ付きPDFを作成するためのチェックボックスがあり(私の記憶が正しければ)、最終的にテーブルのHTMLのようなタグを使用してタグ付きPDFを作成します。非常に原始的ですが、動作します。ただし、このコンテキストを解析するのはあなた次第です。

于 2015-12-31T21:15:00.930 に答える
0

データを抽出するための代替戦略をここに残します。これは、誰が処理される/処理できるスペースの問題を解決しませんが、テキストを抽出する幾何学的領域を指定することで、抽出をより細かく制御できます。ここから撮影。

 public static System.util.RectangleJ GetRectangle(float distanceInPixelsFromLeft, float distanceInPixelsFromBottom, float width, float height)
    {
        return new System.util.RectangleJ(
            distanceInPixelsFromLeft,
            distanceInPixelsFromBottom,
            width,
            height);
    }

      public static void Strategy2()
    {
        // In this example, I'll declare a pageNumber integer variable to
        // only capture text from the page I'm interested in
        int pageNumber = 1;

        var text = new StringBuilder();

        List<Tuple<string, int>> result = new List<Tuple<string, int>>();

        // The PdfReader object implements IDisposable.Dispose, so you can
        // wrap it in the using keyword to automatically dispose of it

        using (var pdfReader = new PdfReader("D:/Example.pdf"))
        {
            float distanceInPixelsFromLeft = 20;
            //float distanceInPixelsFromBottom = 730;
            float width = 300;
            float height = 10;

            for (int i = 800; i >= 0; i -= 10)
            {
                var rect = GetRectangle(distanceInPixelsFromLeft, i, width, height);

                var filters = new RenderFilter[1];
                filters[0] = new RegionTextRenderFilter(rect);

                ITextExtractionStrategy strategy =
                    new FilteredTextRenderListener(
                        new LocationTextExtractionStrategy(),
                        filters);

                var currentText = PdfTextExtractor.GetTextFromPage(
                    pdfReader,
                    pageNumber,
                    strategy);

                currentText =
                    Encoding.UTF8.GetString(Encoding.Convert(
                        Encoding.Default,
                        Encoding.UTF8,
                        Encoding.Default.GetBytes(currentText)));

                //text.Append(currentText);
                result.Add(new Tuple<string, int>(currentText, currentText.Length));
            }
        }

        // You'll do something else with it, here I write it to a console window
        //Console.WriteLine(text.ToString());
        foreach (var line in result.Distinct().Where(r => !string.IsNullOrWhiteSpace(r.Item1)))
        {
            Console.WriteLine("Text: [{0}], Length: {1}", line.Item1, line.Item2);
        }
        //Console.WriteLine("", string.Join("\r\n", result.Distinct().Where(r => !string.IsNullOrWhiteSpace(r.Item1))));

出力:

ここに画像の説明を入力

PS .: スペースや非テキスト データをどのように処理するかという問題が残っています。

于 2016-01-13T11:10:20.973 に答える