Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS Access > VBA| Переименование полей таблицы


Автор: Ethex 14.9.2018, 15:10
Доброго времени суток
Имеется список имён для полей, заданный значением поля со списком на форме. Я пытаюсь переименовать поля выбранной таблицы
Код

Private Sub Кнопка6_Click()
Dim rst As DAO.Recordset, fd As DAO.Field
Dim tableName As String
Dim i As Long
    If Me.ПолеСоСписком0 <> 0 And Me.ПолеСоСписком4 <> 0 Then
    tableName = Me.ПолеСоСписком0
    Set rst = CurrentDb.OpenRecordset(tableName, dbOpenDynaset)
    Dim arrFieldsNames() As String
    arrFieldsNames = Split(Me.ПолеСоСписком4, ", ")
        If rst.Fields.Count - 1 = UBound(arrFieldsNames) Then
        i = 0
            For Each fd In rst.Fields
            rst.Fields(fd.Name).Name = arrFieldsNames(i)
            i = i + 1
            Next
        rst.Close: Set rst = Nothing
        Erase arrFieldsNames
        Else
        Erase arrFieldsNames
        MsgBox "Число полей указанной таблицы не соответствует числу указанных имён для полей"
        Exit Sub
        End If
    Else
    MsgBox "Таблица не выбрана, либо не указан перечень имён для полей "
    End If
MsgBox "Готово"
End Sub

При выполнении строки
Код

rst.Fields(fd.Name).Name = arrFieldsNames(i)

Получаю ошибку "Недопустимая операция". Как избежать?

Автор: Akina 14.9.2018, 20:20
Имя поля тут - RO. Делай через TableDef.

Автор: Ethex 16.9.2018, 19:53
Цитата(Akina @  14.9.2018,  20:20 Найти цитируемый пост)
Делай через TableDef

Имеется в виду использовать TableDef вместо рекордсета?
Ранее я пробовал так
Код

...
Set tdf = CurrentDb.TableDefs(tableName)
...
    For Each fd In tdf.Fields
    fd.Name = arrFieldsNames(i)
    Next
...

Получал ошибку "Указан недопустимый объект или объект более не задан"
Поэтому поводу нашёл такое вот:
Цитата

Под отладчиком видно, что переменна CUR_TBL сначала = Nothing, а потом (после Set) становися действительным указателем, но в процессе выполнения ЛЮБОГО следующего оператора (Даже если после Set поставить X=1) перестает быть действительным. Экспериментально установлено, что объект TableDef прекращает свое существование к началу выполнения следующего оператора (составные операторы рассматриваются как несколько).

ФАНТАСТИКА! Я этого не знал! Т.е. работать с экземпляром объекта TableDef можно только в пределах одного оператора. Потом он разрушается, а указатель на него перестает быть действительнывм. Аналогично обстоит дело с объектами лежащими глубже (Например, ссылка на TableDef(...).Fields ведет себя также). Могу только предположить, что TableDef - это лишь логическое отражение некой физической реальности, которая потенциально может быть изменена другим пользователем (или даже просто другим потоком текущего приложения), и поэтому оно не является, например, потокозащищенным, а посему срок его жизни ограничен одним оператором, который в VBA выполняется в одном потоке в CriticalSection (но это только догадки)

Увы ничего тут не поделаешь! Придется писать громоздкий и неэффективный код!!!

Например цикл 

For Each t In CurrentDb.TableDefs
MsgBox t.Name
Next

РАБОТАЕТ
А цикл 

For Each f In CurrentDb.TableDefs(CUR_TBL_NAME).Fields
MsgBox f.Name
Next

Уже не работает, так как при вхождении в цикл переменная f ссылается на объект Field, но уже на первоой же итерации (т.е. к началу выполнения MsgBox f.Name) оказывается ссылкой на недействительный объект!

Увы....

Вот тут - http://forum.developing.ru/archive/index.php/t-6774.html


Автор: Ethex 17.9.2018, 10:15
Всего-то нужно было обойтись без установки объекта
Код

Private Sub Кнопка6_Click()
Dim tdf As DAO.TableDef, fd As DAO.Field
Dim tableName As String
Dim i As Long
    If Me.ПолеСоСписком0 <> 0 And Me.ПолеСоСписком4 <> 0 Then
    tableName = Me.ПолеСоСписком0
    Dim arrFieldsNames() As String
    arrFieldsNames = Split(Me.ПолеСоСписком4, ", ")
        For Each tdf In CurrentDb.TableDefs
            If tdf.Name = tableName Then
                If tdf.Fields.Count - 1 = UBound(arrFieldsNames) Then
                i = 0
                    For Each fd In tdf.Fields
                    tdf.Fields(i).Name = arrFieldsNames(i)
                    i = i + 1
                    Next
                Erase arrFieldsNames
                Else
                Erase arrFieldsNames
                MsgBox "Число полей указанной таблицы не соответствует числу указанных имён полей"
                Exit Sub
                End If
            End If
        Next
    Else
    MsgBox "Таблица не выбрана либо не указан перечень имён полей"
    End If
MsgBox "Готово"
End Sub



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)