Получить значение ячейки в Excel из диапазона

Как я могу извлечь значение ячейки из объекта диапазона? Вроде должно быть просто. Этот вопрос Stackoverflow и ответы не очень помогли. Вот что я хочу сделать, но каждый раз происходит сбой с исключением для row.columns(0,0).

Dim rdr = oFindings.Range
For Each row As Excel.Range In rdr.Rows
   Dim Account = row.Columns(0,0).value2.tostring
   ' Do other stuff
Next

Чтобы заставить его работать, мне пришлось реализовать этот код:

For Each row As Excel.Range In rdr.Rows
    ndx = 0
    For Each cell As Excel.Range In row.Columns
        If ndx = 0 Then Account = NS(cell.Value2)
        ' Do other stuff
        ndx += 1
    next
Next

Это похоже на такой ляп. В чем секрет?


person Ebassador    schedule 02.09.2015    source источник
comment
Они все одного типа? Вы заранее знаете тип ячейки?   -  person SpaceSteak    schedule 02.09.2015
comment
исключение для row.columns(0,0) кажется логичным, поскольку Excel (и любые 2D-коллекции в VB.NET или на любом другом языке, который я знаю) ожидает только 2 индекса, а вы предоставляете 3. Переменная строка в цикле foreach то же самое, что и rdr.Rows(indexRow); а затем вы добавляете еще два индекса в столбец. Правильный синтаксис: row.Columns(0).   -  person varocarbas    schedule 02.09.2015
comment
0 не является допустимым индексом строки или индексом столбца в Excel VBA   -  person Ron Rosenfeld    schedule 02.09.2015
comment
@RonRosenfeld Во-первых, это не VBA, а во-вторых, 0 является допустимым индексом VBA во многих функциях (но не в ячейках Excel). Проблема здесь в том, что он вводит 3 индекса, а не только 2 (проблема в VBA и здесь, в VB.NET).   -  person varocarbas    schedule 02.09.2015
comment
@varocarbas Спасибо за это разъяснение. Я упомянул в своем комментарии, что он применим к Excel VBA, и на этом языке Columns(0,0) не является допустимой ссылкой на диапазон. Я не уверен, как это может относиться к проблеме ОП, но я чувствовал, что это может быть полезной информацией.   -  person Ron Rosenfeld    schedule 02.09.2015
comment
@RonRosenfeld (возможно, я неправильно понял априори очень четкое предложение 0 не является допустимым индексом строки или индексом столбца в Excel VBA; извините за это, но уточнение никогда не бывает проблемой, не так ли?). В любом случае имейте в виду, что в VBA столбцы (0,0) так же неверны, как и столбцы (2,2), поскольку коллекция Columns() допускает только один индекс (эквивалентно большинству коллекций, называемых столбцами, которые обычно являются частью эмуляции таблицы, например DataTable в .NET). Это уточнение в порядке, или я снова неправильно понял ваше намерение?   -  person varocarbas    schedule 02.09.2015
comment
Просто примечание: настоятельно рекомендуется не использовать row или cell в качестве переменной, потому что Row и Cell означают что-то неявное для VBA. Я бы изменил эту переменную на xRow или cel или что-то в этом роде. Не хочу вызвать путаницу в будущем!   -  person BruceWayne    schedule 02.09.2015
comment
@RonRosenfeld Кому я отдаю должное в этом? Это была проблема использования двух индексов внутри цикла For И Excel основан на 1, а не на нуле. В очередной раз Stackoverflow оказался фантастическим ресурсом! Спасибо большое!   -  person Ebassador    schedule 02.09.2015
comment
@varocarbas Мои извинения. Ваша помощь очень ценится.   -  person Ebassador    schedule 02.09.2015
comment
@varocarbas Я не могу спорить с вашими выводами. Именно поэтому я задал вопрос в первую очередь. Как вы сказали, .Net основан на 0. Однако в этом случае, независимо от того, использовал ли я (0,0) или просто (0), я все равно получил исключение. Кроме того, исправление кода (VB.NET, а не VBA) потребовало, чтобы я использовал (1). Мне жаль, что я не обладаю всеми знаниями, которыми вы, очевидно, обладаете. Я просто стараюсь узнавать что-то новое каждый день. Stackoverflow помогает мне в этом! Я люблю это.   -  person Ebassador    schedule 02.09.2015
comment
@varocarbas Чтобы еще больше прояснить то, что я пытался сделать: rowindex и columnindex - это именованные аргументы для различных объектов диапазона VBA. Я хотел сказать, что в дополнение к тому, что вы уже указали на недопустимость объекта OP Columns с двумя аргументами, в VBA этот аргумент не может быть равен нулю.   -  person Ron Rosenfeld    schedule 02.09.2015
comment
Пара идей для будущих читателей. ИДЕЯ 1: это VB.NET (связанный с Excel через Interop, но полностью полагающийся на правила .NET, например, ВСЕ МАССИВЫ НА ОСНОВЕ 0). ИДЕЯ 2: проблема этого кода заключалась в row.Columns(0,0), которая, как объяснялось выше, неверна (также объяснялись исправления), она также была бы неправильной в VBA из-за использования ДВУХ ИНДЕКСОВ (ноль или любое другое число). ИДЕЯ 3: VBA (не VB.NET) основан на 1 только в определенных частях (например, в ячейках), но не в других (массивы), и он может быть преобразован в основанный на нуле (это просто поведение по умолчанию).   -  person varocarbas    schedule 02.09.2015
comment
Ebassador, вы должны понимать, что тот факт, что он падает в вашей конкретной ситуации, не делает его абсолютно неправильным (может быть, ваш код не идеален?). Если у вас не слишком много знаний о чем-то, и кто-то (очевидно) с гораздо большими знаниями в этом вопросе говорит вам что-то, возможно, вам не следует думать, что случайная интерпретация может быть хороша для спора с таким человеком. Я настаиваю: .NET (все коллекции на любом языке .NET) основаны на нуле; когда вы читаете из Excel, информация сохраняется в коллекции .NET (не имеет ничего общего с VBA), которая основана на 0.   -  person varocarbas    schedule 02.09.2015
comment
PS: наиболее вероятная причина вашей проблемы заключается в том, что вы выполняете .value2.ToString(), не проверяя, действительно ли .value2 имеет значение null (очень плохая идея, потому что, если оно равно null, ToString() не будет существовать, и ошибка будет быть запущенным). Первая ячейка в вашей электронной таблице (rdr.Rows(0).Columns(0) в VB.NET), скорее всего, пуста, значение2 равно нулю, и здесь у вас есть ошибка.   -  person varocarbas    schedule 02.09.2015
comment
@RonRosenfeld Я думаю, что я очень ясно изложил эти идеи в различных комментариях, но на всякий случай здесь приходит новое разъяснение: коллекция Columns в VBA (никак не связана с тем, что обсуждается в этом вопросе, совершенно другая коллекция, имеющая с тем же именем, которое следует правилам VB.NET и, следовательно, основано на 0), основано на 1 (то же самое для строк, ячеек и т. д.). В VBA довольно много вещей (например, массивы), которые основаны на 0 (по крайней мере, по умолчанию; могут быть изменены). В любом случае, настаивая на том, что VB.NET Interop не имеет НИЧЕГО ДЕЛАТЬ с VBA (просто похожий синтаксис).   -  person varocarbas    schedule 02.09.2015
comment
@varocarbas Я согласен, но я писал исключительно о конкретных именованных аргументах, о которых я упоминал, а не о массивах VBA.   -  person Ron Rosenfeld    schedule 02.09.2015
comment
@RonRosenfeld Как уже было сказано, все коллекции, связанные с реальными ячейками (например, столбцы, строки, листы, рабочие книги и т. д.), и довольно много функций на самом деле основаны на 1; но не все в VBA по умолчанию основано на 1.   -  person varocarbas    schedule 02.09.2015


Ответы (1)


О большинстве проблем уже упоминалось, но вот ответ с кодом.

    Dim rdr As Excel.Range = oFindings.Range
    For Each row As Excel.Range In rdr.Rows

        'explicitly get the first cell as a range 
        Dim aCell As Excel.Range = row.Cells(1, 1)

        'explicity convert the value to String but don't use .String
        Dim Account as string = CStr(aCell.Value2)

        If Not String.IsNullOrEmpty(Account) Then

            ' Do other stuff

        End If

    Next

Использование aCell.Value2.toString не удастся, если ячейка пуста, потому что Value2 будет Nothing. Вместо этого используйте CStr(aCell.Value2), который не подведет. Но тогда вам нужно проверить, является ли строка нулевой или пустой, прежде чем использовать значение.

person D_Bester    schedule 03.09.2015