PDA

Показать полную графическую версию : [решено] Проход по строкам таблицы с объединенными ячейками


tumanovalex
23-04-2018, 21:49
Программа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
string[] strDocFileName = Directory.GetFiles(cyrDir, "*.do*", SearchOption.AllDirectories); »
Будут и dot, и dotx, и .do и прочее.
Судя по Directory.GetFiles Method (String, String, SearchOption) (System.IO) (https://msdn.microsoft.com/en-us/library/ms143316(v=vs.110).aspx):
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) на Вашем документе не вызывает ошибки, независимо от того, объединённая ячейка, или нет. Какая именно ошибка возникает — Вы не указали, но, полагаю, что это ошибка адресации: например, Вы пытаетесь обратиться к несуществующему в таблице четвёртому столбцу второй (четвёртой, шестой) строки.

Подскажите, пожалуйста, как:
- перемещаться по строкам таблицы; »
Именно так, как Вы делаете — перебирая строки таблицы.

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

tumanovalex
25-04-2018, 21:02
Дело в том, что я получаю исключение из-за разного количества ячеек в разных строках

Iska
25-04-2018, 21:06
Дело в том, что я получаю исключение из-за разного количества ячеек в разных строках »
Разве я говорю:
но, полагаю, что это ошибка адресации: например, Вы пытаетесь обратиться к несуществующему в таблице четвёртому столбцу второй (четвёртой, шестой) строки. »
что-то иное? Чуть ниже я предложил там простое очевидное решение — проверяйте количество ячеек в строке. Если их четыре — обращайтесь к четвёртому столбцу строки. Если их две — просто пропускайте строку.

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

Iska
26-04-2018, 01:29
foreach(var rTable in tbl.Rows) ошибки не дает, но не понятно, что с этим делать. »
Пользовать :).

Вы у себя в коде перебираете с указанного номера строки до последней:
int numRows = tbl.Rows.Count;

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

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

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

У объекта Table (Table Interface (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.table(v=office.14).aspx)) есть (Table Members (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.table_members(v=office.14).aspx)) свойство .Rows (Table.Rows Property (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.table.rows(v=office.14).aspx)), возвращающее коллекцию (Rows Interface (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.rows(v=office.14).aspx)) из объектов Row (Row Interface (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.row(v=office.14).aspx)), каждый из которых имеет свойство .Cells (Row.Cells Property (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.row.cells(v=office.14).aspx)), возвращающее коллекцию (Cells Interface (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.cells(v=office.14).aspx)) из объектов Cell (Cell Interface (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.cell(v=office.14).aspx)). Эта коллекция, как и любая другая, имеет свойство .Count (Cells.Count Property (Microsoft.Office.Interop.Word) (https://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.cells.count(v=office.14).aspx)).

tumanovalex
26-04-2018, 19:20
Спасибо большое. Удалось разобраться. Получилось определить число ячеек в строке




© OSzone.net 2001-2012