Excel VBA ListRows.Add Fails - PullRequest
       64

Excel VBA ListRows.Add Fails

0 голосов
/ 02 июля 2010

Я, вероятно, упускаю что-то простое, но ListRows.Add дает мне горе. Вот функция:

Sub addEmployee(employeeName As String, tableToAddTo As ListObject)
   Dim newRow As ListRow

   Set newRow = tableToAddTo.ListRows.Add()
   newRow.Range.Cells(1, 1).Value = employeeName
   tableToAddTo.Sort.Apply
End Sub

В большинстве случаев это работает нормально. Однако всякий раз, когда функция запускается на определенной таблице в моей рабочей таблице, строки, следующие за вызовом ListRows.Add, никогда не выполняются (по крайней мере, так указывает отладчик), и строка не добавляется в таблицу. Есть мысли / идеи?

UPDATE:

Вот что я узнал с момента публикации. Если я подпитываю Sub с данными заглушки, это работает отлично. Например:

Sub driver() 
    Dim myTable As ListObject 
    Set myTable = getTableObject("myTableName") 
    Call addEmployee("myName", myTable)
End Sub

Примечание: getTableObject циклически перебирает листы и возвращает ListObject с соответствующим именем.

Кажется, это проблема, связанная с контекстом, в котором вызывается код. В случае неудачи формула (вызов функции) помещается в различные ячейки различных таблиц. Формула содержит ссылки на данные в других ячейках. Когда данные в других ячейках изменяются, вызывается формула, которая, в свою очередь, вызывает подпрограмму addEmployee, приведенную выше. Это тот случай, который терпит неудачу.

Ответы [ 8 ]

3 голосов
/ 03 июля 2010

Похоже, что то, что я пытался сделать, невозможно.

При разработке пользовательских функций важно понимать ключевое различие между функциями, которые вы вызываете, от других процедур VBA и функций, которыевы используете в формулах листа.Процедуры функций, используемые в формулах рабочего листа, должны быть пассивными.Например, код в процедуре Function не может манипулировать диапазонами или что-либо менять на рабочем листе.Пример может помочь прояснить это.

У вас может возникнуть желание написать пользовательскую функцию рабочего листа, которая изменяет форматирование ячейки.Например, может быть полезно иметь формулу, которая использует пользовательскую функцию для изменения цвета текста в ячейке на основе значения ячейки.Как ни старайся, такую ​​функцию написать невозможно.Независимо от того, что вы делаете, функция не изменит лист.Помните, функция просто возвращает значение.Он не может выполнять действия с объектами.

Тем не менее, я должен указать на одно заметное исключение.Изменить текст в ячейке комментарий можно с помощью пользовательской функции VBA.

Walkenbach, J. (2007).Microsoft Office Excel 2007 Power Программирование с VBA.John Wiley & Sons, стр. 280.

2 голосов
/ 05 ноября 2016

Извините за неуместность вопроса, но это единственная публикация StackOverflow, которая появляется в Google при поиске аналогичного сбоя по другой причине.Авария на ListRows.Add довольно долго отвлекала меня, поэтому я поделился проблемой, вызвавшей ее для меня.

На рабочем листе есть таблица (скажем, MySourceTable).В моей пользовательской форме * RowSource ComboBox является столбцом из этой таблицы (MySourceTable [ColName]).Нажав другую кнопку на той же пользовательской форме, я вставлял новую строку, используя ListRows.Add, в эту таблицу и вылетал в Excel.Если этот сценарий похож на ваш, читайте дальше.

Сбой вызван ComboBox, который все еще прикреплен к таблице и не может обработать вставку строк (имейте в виду, что он все еще создаетсяпотому что я все еще на UserForm при вставке новой строки).После большой боли следующие строки над и под вставкой решили ее навсегда:

    comboSetSelect.RowSource = ""
    Set newRow = myTable.ListRows.Add
    comboSetSelect.RowSource = "MySourceTable[ColName]" 'col set in properties

Это отсоединяет ComboBox от таблицы перед вставкой новой строки, и после завершения вставки обновляет ComboBox снова,Кроме того, значение новой вставленной строки (если оно обновляется сразу после вставки) также отображается в ComboBox.

1 голос
/ 23 мая 2016

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

Sub AddRow()
     Dim Tbl as ListObject
     Dim MyColumn as Integer

     Tbl.ListRows(1).Range.EntireRow.Insert
     Tbl.ListColumns(MyColumn).DataBodyRange.Cells(1,1).Value = "My Value"
End Sub

При добавлении новой строки над первой существующей записью таблица автоматически корректируется по назначению, а затем я могу начатьзаписать мои значения в таблицу.

Опять же, извините за восстановление старого поста, но я не смог найти адекватного решения в другом месте, так что это мой собственный обходной путь, который, я надеялся, будет полезен для других в будущем.

0 голосов
/ 24 июня 2019

Короче говоря

tab_.ListRows(1).Range.EntireRow.Insert может (!) Работать вместо tab_.ListRows.Add.
(как уже предлагалось в ответ SandPiper'а )

, инкапсулируя его в более общую функцию , которая также возвращает ListRow:

Function TabRowAdd(tab_ As ListObject) As ListRow
    tab_.ListRows(1).Range.EntireRow.Insert
    Set TabRowAdd = tab_.ListRows(1)
End Function

, вы бы использовали его так: TabRowAdd(tab_) вместо tab_.ListRows.Add

Возможная причина

Если под (или, возможно, даже под) текущей таблицей есть другие ячейки, не относящиеся к таблице, она не будет работать, потому что (Iугадайте) «сворачивание» этого другого контента может вызвать плохие побочные эффекты или может быть более сложным.

Так, например, представьте следующую схему таблицы и как следует вставлять строку в таблицу 1 быть выполнено прямо?(обычно плохой / глупый макет - я знаю :))

| table 1 header |  | table 2 header |
|         row 1  |  |         row 1  |
|         row 2  |  |         row 2  |         
                    |         row 3  |  | table 5 header |
| table 3 header |  |         row 4  |  |         row 1  |
|         row 1  |                      |         row 2  |
|         row 2  |                      |         row 3  |
                                        |         row 4  |
    | table 4 header      |             |         row 5  |
    |         row 1       |

=> это не легко, и поэтому я думаю, что они могут просто проверить, есть ли что-то вне таблицы под или подманипулировать таблицей (вставить строку / столбец, удалить строку / столбец) и, таким образом, выдать исключение 1004.
(может быть, даже после таблиц "не A -колонка-начало" эта проблема уже возникнет - Iне проверял)

0 голосов
/ 24 августа 2017

Другой причиной сбоя ListObject.ListRows.Add может быть защита листа.Так как я не увидел это ни в одном из моих результатов поиска, я хотел бы добавить его сюда для дальнейшего использования.

Если лист был защищен с помощью

worksheet.Protect 

beобязательно

worksheet.Unprotect 

перед применением ListObject.ListRows.Add!

0 голосов
/ 30 сентября 2016

Я знаю, что это старая ветка, я не хочу переиздавать, и я полагаю, у меня есть решение, которое может помочь другим.

Быстрая информация о моих сценариях, у меня есть ListRows.Add in Private Sub BTN_Save_DblClick Я удалил весь свой код и оставил только этот модуль, к моему удивлению сработал, поэтому я начал реализовывать каждую подпрограмму и функцию, пока не добрался до того, который былвызывая проблему.

Оказывается, что (для меня), потому что у меня было UserForm_Initialize () как Private Sub вместо Public Sub , это привело к сбою ListRows , в процессе которого произошел сбой Excel ..

Итак, если у вас возникла эта проблема, и у вас есть UserForm_Initialize () , убедитесь, чтодля него установлено значение Public, а не private.

В любом случае, если это не сработает, тогда это простой процесс удаления, удалите весь код, кроме кода с ListRows и добавьте каждый подпрограмму./ функциональное тестирование каждый раз, пока вы не найдетеНе это вызывает проблему.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ Так что это было временное исправление, он снова начал падать, поэтому я удалил строку кода внутриuserform_initialize и он исправил это снова .. это так странно, потому что все, что он делает, это ComboBox1.RowSource = NamedRange .

У меня никогда не было такого рода проблем с Excel VBA.

0 голосов
/ 05 сентября 2016

Это тоже меня немного напрягало. Мне показалось, что вызов ListRows.Add несколько раз в цикле - вызвало эту ошибку, а иногда и сбой Excel. Решение, которое сработало для меня: я добавил команду DoEvents после команды ListRows.Add:

tbl.ListRows.Add
DoEvents
0 голосов
/ 11 июня 2016

В моем случае таблица была ограничена списком

 Dim intClientRow As Integer
Dim strLstSource As String
strLstSource = frmHNW.lstB01People_List.RowSource
frmHNW.lstB01People_List.RowSource = ""
intClientRow = UpdateTableFromFrame(frmHNW.fraB01People, "Clients_tblClientDetails", True)
If intClientRow > 0 Then
    UpdateTableFromList frmHNW.lstB01Contact_Method, "ClientPeople_tblClientContactMethod", "=getClientID(" & intClientRow & ")"
    UpdateTableFromList frmHNW.lstB01Pref_Days, "ClientPeople_tblClientPrefDay", "=getClientID(" & intClientRow & ")"
    UpdateTableFromList frmHNW.lstB01Pref_Time, "ClientPeople_tblClientPrefTime", "=getClientID(" & intClientRow & ")"
End If

frmHNW.lstB01People_List.RowSource = strLstSource

Форма UpdateTableFromFrame применяет метод lisrows.add к исходной таблице списка.После нескольких часов тестирования я обнаружил, что, когда я не удаляю источник списка, мой метод listrows.add не работает.Поэтому я удалил источник строк из списка перед вызовом UpdateTableFromFrame и восстановил обратно после добавления строки.Это решило проблему

...