Как извлечь текст из офисных документов MS на C #

Я пытался извлечь текст (строку) из MS Word (.doc, .docx), Excel и Powerpoint с помощью C #. Где я могу найти бесплатную и простую библиотеку .Net для чтения документов MS Office? Я пытался использовать NPOI, но у меня не было образца о том, как использовать NPOI.


person Elias Haileselassie    schedule 18.06.2009    source источник


Ответы (10)


Используя PInvokes, вы можете использовать интерфейс IFilter (на Windows). Фильтры IFilters для многих распространенных типов файлов устанавливаются вместе с Windows (их можно просматривать с помощью этот инструмент. Вы можете просто попросить IFilter вернуть вам текст из файла. Существует несколько наборов примеров кода (вот один из таких примеров).

person adrianbanks    schedule 18.06.2009
comment
Интересно ... очень хитрое решение :) - person Skurmedel; 18.06.2009
comment
Не совсем. Это механизм, используемый службой индексирования в Windows, и я думаю, что поиск на рабочем столе также использует его. Я использовал его для индексации PDF-файлов (установив Adobe IFilter - Adobe .com / support / downloads / detail.jsp? ftpID = 2611), все типы документов Office (фильтры IFilter для них устанавливаются вместе с Windows) и несколько других типов файлов. Когда он работает, он работает хорошо. Иногда, однако, вы не получаете обратно текст из IFilter и не можете объяснить, почему. - person adrianbanks; 18.06.2009
comment
Я использовал pInvoke и считаю его превосходным. Чтобы извлечь текст из любого документа, все, что нам нужно сделать, это убедиться, что соответствующий IFilter установлен на машине (или загрузить и установить). Мне нравится эта статья и пример кода формы. Посмотрите на этот codeproject.com/KB/cs /IFilter.aspx для MS Office 2007 - это пакет фильтров MS Office 2007 microsoft.com/downloads/ - person Elias Haileselassie; 19.06.2009
comment
Да, если вы установили PDF iFilter. Вы можете сделать это, установив Acrobat Reader (iFilter устанавливается вместе с ним) или установив iFilter отдельно (adobe.com/support/downloads/detail.jsp?ftpID=4025). [Примечание: доступны другие фильтры PDF iFilters :)] - person adrianbanks; 22.02.2010
comment
2 быстрых вопроса - а) В настоящее время я использую описанный здесь метод - codeproject.com/KB /cs/PDFToText.aspx для извлечения текста из PDF. Чем отличается использование IFilters? б) В связанном вами методе IFilter автор выполняет: TextReader reader = new FilterReader (fileName); Я использую элемент управления FileUpload в ASP.NET, и я не могу получить путь к имени файла, поскольку он не отображается на стороне сервера в целях безопасности. С помощью элемента управления fileUpload на стороне сервера я могу делать только следующее: Stream str = fileUpload1.FileContent; byte b [] = fileUpload1.FileBytes; - person Nick; 22.02.2010
comment
@ user102533: a) Единственная реальная разница в том, что использование IFilter дает вам общий метод извлечения текста из любого поддерживаемого типа файлов. Использование PDFToText характерно для этой библиотеки и для файлов PDF. Если вам нужно сделать это только для файлов PDF, это не имеет большого значения (и может быть лучше, поскольку Adobe IFilter немного темпераментен). б) IFilters работают, когда вы передаете им имя файла. Раньше я сохранял byte [] во временном файле, а затем передавал его имя файла фильтру IFilter. - person adrianbanks; 23.02.2010
comment
Пожалуйста, опубликуйте образец вызова iFilter с помощью pInvoke. - person paparazzo; 27.12.2011

Для файлов Microsoft Word 2007 и Microsoft Word 2010 (.docx) можно использовать Open XML SDK. Этот фрагмент кода откроет документ и вернет его содержимое в виде текста. Это особенно полезно для тех, кто пытается использовать регулярные выражения для анализа содержимого документа Word. Чтобы использовать это решение, вам понадобится ссылка DocumentFormat.OpenXml.dll, которая является частью OpenXML SDK.

См .: http://msdn.microsoft.com/en-us/library/bb448854.aspx

 public static string TextFromWord(SPFile file)
    {
        const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

        StringBuilder textBuilder = new StringBuilder();
        using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(file.OpenBinaryStream(), false))
        {
            // Manage namespaces to perform XPath queries.  
            NameTable nt = new NameTable();
            XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
            nsManager.AddNamespace("w", wordmlNamespace);

            // Get the document part from the package.  
            // Load the XML in the document part into an XmlDocument instance.  
            XmlDocument xdoc = new XmlDocument(nt);
            xdoc.Load(wdDoc.MainDocumentPart.GetStream());

            XmlNodeList paragraphNodes = xdoc.SelectNodes("//w:p", nsManager);
            foreach (XmlNode paragraphNode in paragraphNodes)
            {
                XmlNodeList textNodes = paragraphNode.SelectNodes(".//w:t", nsManager);
                foreach (System.Xml.XmlNode textNode in textNodes)
                {
                    textBuilder.Append(textNode.InnerText);
                }
                textBuilder.Append(Environment.NewLine);
            }

        }
        return textBuilder.ToString();
    }
person KyleM    schedule 28.12.2011
comment
@adrianbanks Я считаю, что этот ответ в настоящее время лучше, чем принятый ответ, потому что принятый ответ не будет работать в определенных версиях Windows и потому что IFilter является устаревшим интерфейсом. Конечно, в то время, когда писался пост Адриана, это было не так. - person KyleM; 28.12.2011
comment
А как насчет SPFile? Аргумент, который вы вводите в функцию, относится к этому типу, и все, что я смог найти о нем, - это пространство имен Microsoft.Sharepoint в Microsoft.Sharepoint.dll - ›и эту dll нелегко найти. На что вы ссылались, чтобы получить SPFile? - person FrenkyB; 30.09.2013
comment
@ user867703 Вам не нужно использовать SPFile. Это был пример. Вы можете использовать любой файл .docx (открытый как двоичный поток). Посмотрите на метод WordprocessingDocument.Open, это важный метод. - person KyleM; 30.09.2013
comment
Я просто изменил SPFile на путь (строку), а в открытом методе использовал только путь - ›он работает. Решение очень простое и понятное. - person FrenkyB; 30.09.2013
comment
@KyleM Это не похоже на работу в 64-битной системе. Я не могу найти dll DocumentFormat.OpenXML для 64-битной системы. Добавление 32 бита не работает. Или я что-то не так делаю? - person Maxsteel; 18.10.2013
comment
@Maxsteel Что ж, ваше приложение должно быть запущено в 32-битном режиме. 64-разрядный процесс не может загрузить 32-разрядную .dll. Все сборки, загруженные определенным процессом, должны соответствовать разрядности этого процесса. - person KyleM; 18.10.2013
comment
@KyleM Привет, спасибо за ответ. Оказывается, мне просто пришлось сменить фреймворк с 2.0 на 3.5. И это работает в моем 64-битном проекте, просто для подтверждения. Спасибо, в любом случае :) - person Maxsteel; 19.10.2013
comment
@Maxsteel Рад, что у вас все заработало, но то, что я сказал, было правильным. См. stackoverflow.com/questions/ 2265023 / - person KyleM; 20.10.2013
comment
В пакете OpenXML вам нужно импортировать: DocumentFormat.OpenXml.Packaging DocumentFormat.OpenXml.Wordprocessing И вам нужно указать WindowsBase.dll, чтобы он работал. Помимо этого; хорошее решение. - person Kristian Barrett; 09.12.2014
comment
@KristianBarrett Спасибо. Если вы обратитесь к DLL, о которой я упоминал в сообщении, я думаю, Visual Studio сообщит вам, какие пакеты нужно импортировать. Хотя прошло некоторое время, поэтому спасибо за точный импорт всем, кто в них нуждается. - person KyleM; 10.12.2014

Tika очень полезна и легко извлекает текст из различных документов, включая файлы Microsoft Office.

Вы можете использовать этот замечательный проект, сделанный Кевином Миллером http://kevm.github.io/tikaondotnet/

Просто добавьте этот пакет NuGet https://www.nuget.org/packages/TikaOnDotNet/

а затем эта одна строка кода сотворит чудеса:

var text = new TikaOnDotNet.TextExtractor().Extract("fileName.docx  / pdf  / .... ").Text;
person Dina    schedule 23.11.2015
comment
Это тот пакет, который вам нужен: nuget.org/packages/TikaOnDotnet.TextExtractor - person Nine Tails; 26.04.2017
comment
Здесь стоит отметить, что это фактически запускает Apache Tika (java) через IKVM, который является средой выполнения .net для java, поэтому это не легкое решение. (40 МБ двоичных файлов, в основном вся среда выполнения java) - person caesay; 01.03.2018

Позвольте мне немного поправить ответ, данный KyleM. Я просто добавил обработку двух дополнительных узлов, которые влияют на результат: один отвечает за горизонтальную табуляцию с «\ t», другой - за вертикальную табуляцию с «\ v». Вот код:

    public static string ReadAllTextFromDocx(FileInfo fileInfo)
    {
        StringBuilder stringBuilder;
        using(WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(dataSourceFileInfo.FullName, false))
        {
            NameTable nameTable = new NameTable();
            XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(nameTable);
            xmlNamespaceManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");

            string wordprocessingDocumentText;
            using(StreamReader streamReader = new StreamReader(wordprocessingDocument.MainDocumentPart.GetStream()))
            {
                wordprocessingDocumentText = streamReader.ReadToEnd();
            }

            stringBuilder = new StringBuilder(wordprocessingDocumentText.Length);

            XmlDocument xmlDocument = new XmlDocument(nameTable);
            xmlDocument.LoadXml(wordprocessingDocumentText);

            XmlNodeList paragraphNodes = xmlDocument.SelectNodes("//w:p", xmlNamespaceManager);
            foreach(XmlNode paragraphNode in paragraphNodes)
            {
                XmlNodeList textNodes = paragraphNode.SelectNodes(".//w:t | .//w:tab | .//w:br", xmlNamespaceManager);
                foreach(XmlNode textNode in textNodes)
                {
                    switch(textNode.Name)
                    {
                        case "w:t":
                            stringBuilder.Append(textNode.InnerText);
                            break;

                        case "w:tab":
                            stringBuilder.Append("\t");
                            break;

                        case "w:br":
                            stringBuilder.Append("\v");
                            break;
                    }
                }

                stringBuilder.Append(Environment.NewLine);
            }
        }

        return stringBuilder.ToString();
    }
person Jordan    schedule 02.07.2014
comment
Как извлечь изображения, если они есть внутри w: p? - person Shuaib; 11.05.2017

Используйте Microsoft Office Interop. Это бесплатно и красиво. Вот как я вытащил все слова из документа.

    using Microsoft.Office.Interop.Word;

   //Create Doc
    string docPath = @"C:\docLocation.doc";
    Application app = new Application();
    Document doc = app.Documents.Open(docPath);

    //Get all words
    string allWords = doc.Content.Text;
    doc.Close();
    app.Quit();

Затем делайте со словами все, что хотите.

person Chris    schedule 19.10.2016
comment
Ах, молодец мой друг. Теперь это должен быть принятый ответ, остальные устарели. - person Hugo Nava Kopp; 27.10.2016
comment
Это очень простое, но очень медленное решение. Open XML в тысячи раз быстрее. - person buks; 04.11.2016
comment
Это бесплатно - разве не требуется, чтобы у вас был установлен Word? - person Matt Burland; 04.01.2019
comment
@Chris: И, судя по тексту catch22 Мэтта Берланда, как мне запустить это на сервере Linux? ;) - person Stefan Steiger; 26.04.2019

Немного поздно для вечеринки, но тем не менее - в настоящее время вам не нужно ничего загружать - все уже установлено с .NET: (просто не забудьте добавить ссылки на System.IO.Compression и System.IO.Compression.FileSystem)

using System;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml;
using System.Text;
using System.IO.Compression;

public static class DocxTextExtractor
{
    public static string Extract(string filename)
    {
        XmlNamespaceManager NsMgr = new XmlNamespaceManager(new NameTable());
        NsMgr.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");

        using (var archive = ZipFile.OpenRead(filename))
        {
            return XDocument
                .Load(archive.GetEntry(@"word/document.xml").Open())
                .XPathSelectElements("//w:p", NsMgr)
                .Aggregate(new StringBuilder(), (sb, p) => p
                    .XPathSelectElements(".//w:t|.//w:tab|.//w:br", NsMgr)
                    .Select(e => { switch (e.Name.LocalName) { case "br": return "\v"; case "tab": return "\t"; } return e.Value; })
                    .Aggregate(sb, (sb1, v) => sb1.Append(v)))
                .ToString();
        }
    }
}
person lxa    schedule 15.09.2016
comment
Это похоже на отличное решение, но я не могу с этим справиться, так как получаю сообщение об ошибке: Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. - person Hugo Nava Kopp; 24.03.2017
comment
Это сообщение похоже на ZipFile представление о том, что zip-файл (то есть файл docx в данном случае) поврежден ... - person lxa; 26.03.2017
comment
это не работает, потому что не сохраняет концы строк. - person Gullbyrd; 12.03.2020

Простой!

Эти два шага приведут вас к этому:

1) Используйте библиотеку взаимодействия Office для преобразования DOC в DOCX
2) Используйте DOCX2TXT для извлечения текста из нового DOCX

Ссылка для 1) содержит очень хорошее объяснение того, как выполнить преобразование, и даже образец кода.

Альтернатива 2) - просто распаковать файл DOCX на C # и просканировать файлы, которые вам нужны. Вы можете прочитать о структуре ZIP-файла здесь.

Изменить: Ах, да, я забыл указать, как это сделал Скурмедель ниже, что у вас должен быть установлен Office в системе, в которой вы хотите выполнить преобразование.

person joshcomley    schedule 18.06.2009
comment
Единственная печальная часть библиотеки взаимодействия с Office заключается в том, что вам необходимо установить Office. - person Skurmedel; 18.06.2009
comment
Interop можно использовать, но по возможности его следует избегать. - person Tun; 21.10.2011
comment
Библиотека объектов Microsoft Word 12.0 - ›Этого нет в моем списке« Добавить ссылку »при щелчке правой кнопкой мыши« Добавить ссылку ». Есть ли другой способ ввода библиотеки объектов Microsoft Word 12.0, чтобы я мог читать в текстовом документе. - person Doug Hauf; 20.12.2013
comment
Interop не работает на хостинге godaddy. Дня поддержки офиса. - person Hardik Mandankaa; 17.06.2016

Однажды я сделал экстрактор текста docx, и это было очень просто. В основном docx и другие (новые) форматы, которые я предполагаю, представляют собой zip-файл с кучей XML-файлов. Текст можно извлечь с помощью XmlReader и только .NET-классов.

Кажется, у меня больше нет кода :(, но я нашел парня, у которого есть похожий решение.

Возможно, это невыгодно для вас, если вам нужно читать файлы .doc и .xls, поскольку они являются двоичными форматами и, вероятно, их намного сложнее анализировать.

Существует также OpenXML SDK, все еще в CTP, выпущенный Microsoft.

person Skurmedel    schedule 18.06.2009
comment
это действительно здорово! Я закончил с docx, а что насчет остального? - person Elias Haileselassie; 18.06.2009
comment
Я думаю, вы можете подключиться к xslx-файлу, как к базе данных с ODCB. Думаю, довольно громоздкое решение. Я понятия не имею, как читать .doc-файлы или .xls-файлы, поэтому ничем не могу вам помочь. Вот ссылка на файлы .xls: sc.openoffice.org/excelfileformat.pdf - person Skurmedel; 18.06.2009
comment
К сожалению, я не смог найти на XLSX ничего лучше, чем сама спецификация: ecma-international.org/publications/files/ECMA-ST/ - person Skurmedel; 18.06.2009

Если вы ищете варианты asp.net, взаимодействие не будет работать, если вы не установите офис на сервере. Даже тогда Microsoft говорит не делать этого.

Я пользовался Spire.Doc, прекрасно работало. Spire.Doc загрузить It даже читал документы, которые на самом деле были .txt, но были сохранены .doc. У них есть бесплатная и платная версии. Вы также можете получить пробную лицензию, которая удаляет некоторые предупреждения из документов, которые вы создаете, но я их не создавал, а просто искал их, поэтому бесплатная версия работала как шарм.

person Erik Felde    schedule 23.06.2017
comment
Эрик Фельде, не могли бы вы привести пример для asp.net на Spire.Doc - person Maksud; 25.09.2018

Одним из подходящих вариантов извлечения текста из документов Office на C # является GroupDocs.Parser для .NET API. Ниже приведены примеры кода для извлечения как простого, так и форматированного текста.

Извлечение текста

// Create an instance of Parser class
using(Parser parser = new Parser("sample.docx"))
{
    // Extract a text into the reader
    using(TextReader reader = parser.GetText())
    {
        // Print a text from the document
        // If text extraction isn't supported, a reader is null
        Console.WriteLine(reader == null ? "Text extraction isn't supported" : reader.ReadToEnd());
    }
}

Извлечение форматированного текста

// Create an instance of Parser class
using (Parser parser = new Parser("sample.docx"))
{
    // Extract a formatted text into the reader
    using (TextReader reader = parser.GetFormattedText(new FormattedTextOptions(FormattedTextMode.Html)))
    {
        // Print a formatted text from the document
        // If formatted text extraction isn't supported, a reader is null
        Console.WriteLine(reader == null ? "Formatted text extraction isn't suppported" : reader.ReadToEnd());
    }
}

Уведомление: я работаю евангелистом разработчиков в GroupDocs.

person Usman Aziz    schedule 09.10.2019