C# выделить в DOCX файле подстроки

178
27 апреля 2019, 00:40

Есть docx файл с примерно таким содержимым:

ФИО Иванов Иван Иванович
Дата рожд. 01.01.1967
Должность: Слесарь III разряда
Время работы: 05.03.2000-01.05.2010

Нужно регулярное выражение для выделения подстрок:

Иванов Иван Иванович
01.01.1990
Слесарь III разряда.
05.03.2000-01.05.2010

Использую Spire.Doc

Spire.Doc.Document d = new Document();  
d.LoadFromFile(filepath);
Spire.Doc.Documents.TextSelection sel = d.FindPattern(regex);

этот вариант

Regex regFIO = new Regex(@"фио\s*([\s\S]+?)+\s", RegexOptions.IgnoreCase);  

находит только Иванов Иван. Как составить регэкс для ФИО? Остальное по аналогии сам попытаюсь

Answer 1

Если почитать документацию, поэкспериментировать, то можно обнаружить, что фамилию можно извлечь таким образом

TextSelection fioTs = _document.FindString("ФИО", true, true);
ITextRange[] fioTrs = fioTs.GetRanges();
string fio = (fioTrs[0].NextSibling as ITextRange).Text;

Однако не все так просто... Например строка с днем рожд. порождает 3 TextRange, причем у последнего NextSibling будет не TextRange типа. Пришлось написать несколько сложнее.

Класс куда сохраним извлеченную информацию

class Person
{
    public string FIO { get; set; }
    public string Birthday { get; set; }
    public string Position { get; set; }
    public string WorkTime { get; set; }
}

Основной рабочий класс

class DocService
{
    private readonly string _pathToFile;
    private Document _document;
    private const string _FIO = "ФИО";
    private const string _BIRTHDAY = "Дата рожд.";
    private const string _POSITION = "Должность:";
    private const string _WORK_TIME = "Время работы:";
    //ctor
    public DocService(string pathToFile)
    {
        _pathToFile = pathToFile;
    }
    internal Person GetPerson()
    {
        if (_document == null) LoadDocument();
        List<ITextRange> foundRanges = new List<ITextRange>();
        var tsFio = _document.FindString( _FIO, true, true);
        var trFio = tsFio.GetRanges();
        foundRanges.AddRange(trFio);
        var tsBirthday = _document.FindString(_BIRTHDAY, true, true);
        var trBirthday = tsBirthday.GetRanges();
        foundRanges.AddRange(trBirthday);
        var tsPosition = _document.FindString(_POSITION, true, true);
        var trPosition = tsPosition.GetRanges();
        foundRanges.AddRange(trPosition);
        var tsTime = _document.FindString(_WORK_TIME, true, true);
        var trTime = tsTime.GetRanges();
        foundRanges.AddRange(trTime);

        List<IDocumentObject> nodes = GetAllObjects();
        //получаем ноды типа TextRange за исключением найденных ранее
        var textRanges = nodes
                             .Where(node => node.DocumentObjectType == DocumentObjectType.TextRange)
                             .Except(foundRanges)
                             .Cast<ITextRange>()
                             .ToList();
        var result = new Person
        {
            FIO = textRanges[0].Text,
            Birthday = textRanges[1].Text,
            Position = textRanges[2].Text,
            WorkTime = textRanges[3].Text
        };
        return result;
    }

    private void LoadDocument()
    {
        _document = new Document();
        try
        {
            _document.LoadFromFile(_pathToFile);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Ошибка чтения файла: {ex.Message}");
        }
    }
    private List<IDocumentObject> GetAllObjects()
    {
        List<IDocumentObject> nodes = new List<IDocumentObject>();
        Queue<ICompositeObject> containers = new Queue<ICompositeObject>();
        containers.Enqueue(_document);
        while (containers.Count > 0)
        {
            ICompositeObject container = containers.Dequeue();
            DocumentObjectCollection docObjects = container.ChildObjects;
            foreach (DocumentObject docObject in docObjects)
            {
                nodes.Add(docObject);
                if (docObject is ICompositeObject)
                {
                    containers.Enqueue(docObject as ICompositeObject);
                }
            }
        }
        return nodes;
    }
}

Получается так

P.S. Надеюсь всем понятно, что данный пример работает, только в случае документа, содержащего строки из примера. Если же в документе будет что-то еще, то нужно далее работать с фильтрацией нод.

READ ALSO
Растровая развертка круга

Растровая развертка круга

Как выглядит алгоритм растровой развертки КРУГА по алгоритму Брезенхема? На просторах интернета могу найти только алгоритм развертки окружности...

212
Аналог в c# многомерного массива строк из php

Аналог в c# многомерного массива строк из php

как в C# в массив string[] добавить значения типа многомерного как в php типа такого

230
Запись в локальную переменную из потока

Запись в локальную переменную из потока

При нажатии кнопки "указать", указывается путь к папке с файлами, получается список файлов и по очередной загружается в picturebox и параллельно...

157
Цепочное освобождение объектов

Цепочное освобождение объектов

Все объекты являются неуправляемыми за исключением некоторых типов

164