Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] Проход по строкам таблицы с объединенными ячейками (http://forum.oszone.net/showthread.php?t=334478)

tumanovalex 23-04-2018 21:49 2810428

Проход по строкам таблицы с объединенными ячейками
 
Программа
Код:

using System;
using System.Configuration;
using Word = Microsoft.Office.Interop.Word;
using System.Collections.Generic;
using System.IO;
using System.Configuration;

namespace CsWordCons
{
  class Program
  {

    static void GetFindString(int numRowBegin, int numCol)
    {
      string cyrDir = Environment.CurrentDirectory;
      string[] strDocFileName = Directory.GetFiles(cyrDir, "*.do*", SearchOption.AllDirectories);
      if (strDocFileName.Length > 1)
      {
        Console.WriteLine("Рядом с программой должен быть один файл с расширением doc или docx!");
        Console.ReadKey();
        Environment.Exit(1);
      }
      Object missing = System.Reflection.Missing.Value;
      Object confConv = false;
      Object readOnly = true;
      Object isVisible = false;
      Object saveChanges = false;
      Object filename = strDocFileName[0];
      Word.Application word = new Word.Application();
      Word.Document doc = new Word.Document();
      doc = word.Documents.Open(ref filename, ref confConv, ref readOnly);
      word.Visible = false;
      Word.Table tbl = null;
      try
      {
        tbl = doc.Tables[1];
      }
      catch (Exception ex)
      {
        Console.WriteLine("В документе " + strDocFileName[0] + " нет таблиц!");
        ((Word._Document)doc).Close(ref saveChanges, missing, missing);
        ((Word._Application)word).Quit(ref saveChanges);
        Console.ReadKey();
        Environment.Exit(1);
      }
      int numRows = tbl.Rows.Count;
      List<string> strListFind = new List<string>();
      for (int i = numRowBegin; i <= numRows; i++)
      {
        string[] strOnlyFind = tbl.Cell(i, numCol).Range.Text.Split('\r');
        foreach (string str in strOnlyFind)
        {
          if (str.Length > 2)
            strListFind.Add(str.Trim());
        }
      }
      Console.WriteLine("Будет проведен поиск следующих серийных номеров:");
      foreach (string str in strListFind)
        Console.WriteLine(str);
      Console.WriteLine("---------------------------------------------");
      Console.WriteLine("Нажмите любую клавишу для поиска.\nЕсли серийные номера определены неправильно - проверьте\n" +
                        "данные в конфигурационном файле");
      Console.ReadKey();
      ((Word._Document)doc).Close(ref saveChanges, missing, missing);
      ((Word._Application)word).Quit(ref saveChanges);
    } // GetFindString

    static void Main(string[] args)
    {
      Configuration config = ConfigurationManager.OpenExeConfiguration("CsWordCons.exe");
      string[] allKeys = config.AppSettings.Settings.AllKeys;
      int numKeys = allKeys.Length;
      string strNumRowBegin = config.AppSettings.Settings[allKeys[0]].Value;
      string strNumCol = config.AppSettings.Settings[allKeys[1]].Value;
      string strResultFileName = config.AppSettings.Settings[allKeys[numKeys - 1]].Value;
      GetFindString(int.Parse(strNumRowBegin), int.Parse(strNumCol));
      Console.ReadKey();
    } // Main
  } //class Program
} // namespace CsWordCons

нормально работает, если в таблице нет строк с объединенными ячейками. Если они есть, то в строке string[] strOnlyFind = tbl.Cell(i, numCol).Range.Text.Split('\r'); - ошибка.
Подскажите, пожалуйста, как:
- перемещаться по строкам таблицы;
- определить, что в строке объединены ячейки. Проект прикрепил.

Iska 23-04-2018 22:38 2810431

Цитата:

Цитата tumanovalex
Код:

string[] strDocFileName = Directory.GetFiles(cyrDir, "*.do*", SearchOption.AllDirectories);
»

Будут и dot, и dotx, и .do и прочее.
Скрытый текст
Судя по Directory.GetFiles Method (String, String, SearchOption) (System.IO):
Цитата:

When you use the asterisk wildcard character in a searchPattern such as "*.txt", the number of characters in the specified extension affects the search as follows:
  • If the specified extension is exactly three characters long, the method returns files with extensions that begin with the specified extension. For example, "*.xls" returns both "book.xls" and "book.xlsx".
  • In all other cases, the method returns files that exactly match the specified extension. For example, "*.ai" returns "file.ai" but not "file.aif".
When you use the question mark wildcard character, this method returns only files that match the specified file extension. For example, given two files, "file1.txt" and "file1.txtother", in a directory, a search pattern of "file?.txt" returns just the first file, whereas a search pattern of "file*.txt" returns both files.
достаточным и более правильным будет использовать просто «*.doc».


Мне не очень понятно, чего Вы хотите добиться в целом этим:
Код:

string[] strOnlyFind = tbl.Cell(i, numCol).Range.Text.Split('\r');
У меня нет С++, но в VBA аналогичный оператор Split(tbl.Cell(…, …).Range.Text, vbCr) на Вашем документе не вызывает ошибки, независимо от того, объединённая ячейка, или нет. Какая именно ошибка возникает — Вы не указали, но, полагаю, что это ошибка адресации: например, Вы пытаетесь обратиться к несуществующему в таблице четвёртому столбцу второй (четвёртой, шестой) строки.

Цитата:

Цитата tumanovalex
Подскажите, пожалуйста, как:
- перемещаться по строкам таблицы; »

Именно так, как Вы делаете — перебирая строки таблицы.

Цитата:

Цитата tumanovalex
- определить, что в строке объединены ячейки. »

Определить можно, но зачем? Танцевать всё равно нужно от структуры документа. Со структурой явно видится определённая жёппа, судя по тому, что номера п/п присвоены всем подряд строкам таблицы. Так бы можно было ориентироваться на номера — есть номер п/п, нет номера п/п. А что делать в этом случае? Лично я бы попробовал считать число ячеек в строке, наподобие:
Скрытый текст

tumanovalex 25-04-2018 21:02 2810752

Дело в том, что я получаю исключение из-за разного количества ячеек в разных строках

Iska 25-04-2018 21:06 2810754

Цитата:

Цитата tumanovalex
Дело в том, что я получаю исключение из-за разного количества ячеек в разных строках »

Разве я говорю:
Цитата:

Цитата Iska
но, полагаю, что это ошибка адресации: например, Вы пытаетесь обратиться к несуществующему в таблице четвёртому столбцу второй (четвёртой, шестой) строки. »

что-то иное? Чуть ниже я предложил там простое очевидное решение — проверяйте количество ячеек в строке. Если их четыре — обращайтесь к четвёртому столбцу строки. Если их две — просто пропускайте строку.

tumanovalex 25-04-2018 21:25 2810758

Извините, невнимательно прочитал.
foreach(var rTable in tbl.Rows) ошибки не дает, но не понятно, что с этим делать. Было бы здорово, если бы можно было определить, как у Вас в коде, количество ячеек в rTable, но в C# у rTable, в отличие от VB, нет нужного метода.

Iska 26-04-2018 01:29 2810787

Цитата:

Цитата tumanovalex
foreach(var rTable in tbl.Rows) ошибки не дает, но не понятно, что с этим делать. »

Пользовать :).

Вы у себя в коде перебираете с указанного номера строки до последней:
Код:

int numRows = tbl.Rows.Count;

for (int i = numRowBegin; i <= numRows; i++)

— вот и вся разница. Кстати, для чего — именно с указанного номера строки, а не все зараз, с первой и по последнюю?

Цитата:

Цитата tumanovalex
Было бы здорово, если бы можно было определить, как у Вас в коде, количество ячеек в rTable, но в C# у rTable, в отличие от VB, нет нужного метода. »

Есть (но не у Table, разумеется). Методы, свойства и события Automation определяются объектной моделью приложения, а не используемым языком. Они будут аналогичны и для VBA, и для C#.

У объекта Table (Table Interface (Microsoft.Office.Interop.Word)) есть (Table Members (Microsoft.Office.Interop.Word)) свойство .Rows (Table.Rows Property (Microsoft.Office.Interop.Word)), возвращающее коллекцию (Rows Interface (Microsoft.Office.Interop.Word)) из объектов Row (Row Interface (Microsoft.Office.Interop.Word)), каждый из которых имеет свойство .Cells (Row.Cells Property (Microsoft.Office.Interop.Word)), возвращающее коллекцию (Cells Interface (Microsoft.Office.Interop.Word)) из объектов Cell (Cell Interface (Microsoft.Office.Interop.Word)). Эта коллекция, как и любая другая, имеет свойство .Count (Cells.Count Property (Microsoft.Office.Interop.Word)).

tumanovalex 26-04-2018 19:20 2810943

Спасибо большое. Удалось разобраться. Получилось определить число ячеек в строке


Время: 23:04.

Время: 23:04.
© OSzone.net 2001-