powered by simpleCommunicator - 2.0.41     © 2025 Programmizd 02
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / FAQ. Что мы знаем про каунтеры (aka счетчики)
25 сообщений из 176, страница 4 из 8
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32297065
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эй, факописатели!
Кто нить проверял Q1 A1?
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32297263
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Видимо, нет, потому что про обработчик ошибок там сказано, что "можно сделать". Если можно - значит не пробовали.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32297309
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Надо дать примечание. Возможности DefaultValue в поле таблицы ограничены. Поэтому все эти хитрые функции приходится использовать либо в DefaultValue поля на форме, либо в программе, которая добавляет запись через рекордсет, либо в запросе на добавление.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32297316
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Надо дать примечание.
Список функций, разрешенных для использования в дефаултвалуе, ограничен.

перенесите меня на лестницу плиз
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32312564
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Очередная версия. Надеюсь, что последняя.

Q: Как создать свой счетчик (чтобы поле было не типа счетчик)?

A: Надо написать функцию, к которой обращаться либо в DefaultValue контрола (к сожалению, DefaultValue поля в таблице допускает только ограниченный набор стандартных функций), либо в программе, которая добавляет запись через рекордсет, либо в запросе на добавление. Ниже приведено несколько вариантов такой функции. Особое внимание надо уделить обработчику ошибок.

Вариант 1:

Код: plaintext
Nz(DMax(...), 0 )+ 1 

Так можно нумеровать записи даже внутри группы, а не только насквозь через всю таблицу. Для этого надо правильно задать параметры DMax.

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

Вариант 2: Заводим отдельную таблицу с одним полем типа счетчик и без данных. Приводимая ниже процедура обращается к такой таблице и возвращает очередное значение для "нашего" счетчика. Внимание - файл, в котором сидит эта таблица, запрещено сжимать.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
Function Cou() As Long

Dim ws As Workspace, db As Database
Dim rsCounter As Recordset

On Error GoTo errCou
Set ws = DBEngine( 0 )
Set db = CurrentDb
 1 
ws.BeginTrans
 2 
Set rsCounter = db.OpenRecordset( "select * from tabCounter" )
 3 
rsCounter.AddNew
Cou = rsCounter!nCounter
'Close without update!'
rsCounter.Close
 4 
ws.CommitTrans
 5 
Exit Function

errCou:
Select Case Erl
    Case  3 
        rsCounter.Close
        Set rsCounter = Nothing
        ws.Rollback
        DBEngine.Idle DB_FREELOCKS
        Resume  1 
    Case  2 ,  4 
        ws.Rollback
        DBEngine.Idle DB_FREELOCKS
        Resume  1 
    Case Else
        Resume Next
End Select

End Function 

Подвариант: все-таки делать rsCounter.Update, тогда по виду этой таблицы будет сразу ясно, какое значение было выдано последним. Правда, в этом случае файл станет расти.

Вариант 3 (от Гетца): Держим в отдельной таблице очередное значение счетчика и каждый раз увеличиваем его на 1. Таблица блокируется на момент чтения и увеличения счетчика, а все, кто в нее будут в это время стучаться, спокойно ждут (см. обработчик ошибок adhGetNextAutoNumber_Err) освобождения таблицы.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
Function adhGetNextAutoNumber(ByVal strTableName As String) As Long

    On Error GoTo adhGetNextAutoNumber_Err

    Dim wrk As dao.Workspace
    Dim db As dao.Database
    Dim rstAutoNum As dao.Recordset
    Dim lngW As Long
    Dim lngX As Long
    Dim intRetryCount As Integer
    
    Randomize
    DoCmd.Hourglass True
    intRetryCount =  0 

    Set wrk = dao.DBEngine.Workspaces( 0 )
    Set db = wrk.OpenDatabase(adhCurrentDBPath() & adhcAutoNumDb, False)
    Set rstAutoNum = db.OpenRecordset(strTableName &  "_ID" , dbOpenTable, dbDenyRead)

    rstAutoNum.MoveFirst
    rstAutoNum.Edit
    rstAutoNum!NextAutoNumber = rstAutoNum!NextAutoNumber +  1 
    rstAutoNum.Update
 
    adhGetNextAutoNumber = lngNextAutoNum

adhGetNextAutoNumber_Exit:
    DoCmd.Hourglass False
    On Error Resume Next
    rstAutoNum.Close
    Set rstAutoNum = Nothing
    db.Close
    Set db = Nothing
    wrk.Close
    Set wrk = Nothing
    Exit Function

adhGetNextAutoNumber_Err:
    Select Case Err.Number
        Case adhcErrRI, adhcLockErrCantUpdate2, adhcLockErrTableInUse
            intRetryCount = intRetryCount +  1 
            If intRetryCount > adhcLockRetries Then
                adhGetNextAutoNumber = - 1 
                Resume adhGetNextAutoNumber_Exit
            Else
                dao.DBEngine.Idle
                lngW = intRetryCount ^  2  * _
                  Int((adhcLockUBound - adhcLockLBound +  1 ) * Rnd() + adhcLockLBound)
                For lngW =  1  To lngW
                    DoEvents
                Next lngW
                Resume
            End If
        Case Else
            MsgBox  "Error "  & Err.Number &  ": "  & Err.Description, _
             vbOKOnly + vbCritical,  "adhGetNextAutoNumber" 
            adhGetNextAutoNumber = - 1 
            Resume adhGetNextAutoNumber_Exit
    End Select

End Function

Q: Как заставить счетчик начать выдавать значения начиная с некоторой заданной величины?

A1: Добавить в таблицу со счетчиком при помощи инсерта запись, в которой полю счетчика дается значение на 1 меньше, чем надо. Потом удалить эту запись. Способ работает только при условии, что этот счетчик этого или большего значения еще не выдавал. (Если таким образом дать счетчику отрицательное значение, то он начнет выдавать отрицательные значения, несмотря на то что уже выдавал значения, большие их. Играя на этом, можно добиться, чтобы счетчик выдавал любые значения, в т.ч. и те, которые уже были.)

A2: Сжать базу, в которой сидит таблица со счетчиком. Счетчик будет выдавать значения начиная с наибольшего из существующих +1. В некоторых версиях Аксесса это работает только при условии, что таблица со счетчиком пуста (и тогда счетчик начнет выдавать значения с 1).

A3: Начиная с Аксесса 2000, можно запустить запрос наподобие такого:

Код: plaintext
alter table Таблица1 alter column ПолеСчетчик counter( 1 , 1 )

Q: Может ли поле счетчика содержать повторяющиеся значения?

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

Q: В таблице есть счетчик, но его значения идут не подряд, несколько чисел в середине отсутствуют. Как перезаполнить поле, чтобы дырок не было?

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

Q: Как сымитировать счетчик в отчете?

A: Заводим текстбокс и задаем ему свойства:

Код: plaintext
1.
ControlSource =  "=1 "
RunningSum = True

Q: Как сымитировать счетчик в запросе на добавление?

A: Пишем функцию примерно такого вида:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Function MyFun(Optional iStartValue As Variant) As Long
Static n As Long
If IsMissing(iStartValue) Then
    MyFun = n
    n = n +  1 
Else
    n = iStartValue
    MyFun = True
End If
End Function

В запросе обращаемся к ней дважды:

в части WHERE - с параметром N, где N равно нужному начальному значению счетчика;

в части SELECT - без параметра.

И еще есть парочка вопросов, которые будут добавлены.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32312669
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Код: plaintext
Отмодерировано автором. Узнать, что тут было, можно в ответе Лоха.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32312700
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Саныч, что это было? В смысле какая бешеная лошадь тебе последний вопрос-ответ сказала?

Известно, что при редактировании записи блокируется (от редактирования другими пользователями) не только эта запись, но и вся "страница"
А у меня другая информация :). Умные книги утверждают, что прогресс таки победил и в аксесе уже несколько лет как сделали блокировку отдельных записей.

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

Соответственно, если одну из них кто-то начнет редактировать, то меньше вероятность, что заблокированными будут другие.
С чего это вдруг? Как были заблокированы записи в количестве одной страницы, так и остались заблокированы записи в количестве одной страницы. И вероятность не меньше и не больше, а ровно 100%.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32312730
Фотография Нуф-нуф
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Драсте...
Саныч, ЛП как обычно категоричен (хотя, блин, "морозы" исчезли:), но я тоже смутно припоминаю, что счетчики со случайными значениями используются в реплицируемых БД. Типа, меньше шансов, что в разных БД появятся записи с одинаковым ключом и, соответственно, объединение этих БД пройдет более "мягко".
Хотя, с другой стороны, в реплицируемых БД вроде GUIDы используются... Вообщем, я это... просто поздороваться зашел
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32312738
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
ОК, уберу этот кусок нафиг. :^)
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32312745
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Нуф-Нуф
Морозы не исчезли, просто зима наступила в реале. И так холодно, а от песен совсем труба. Буду вспоминать теплую летнюю песню, как вспомню - буду петь.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32318151
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Q: Как получить значение счетчика только что добавленной записи?

A1: Если запись добавляется через рекордсет, то так:

Код: plaintext
1.
2.
3.
rs.AddNew
переменная = rs!полесчетчика
...
rs.Update

A2: Более широкий круг применимости у такого способа:

Код: plaintext
1.
2.
3.
4.
Dim rs As New ADODB.Recordset
CurrentProject.Connection.Execute  "INSERT ..." 
rs.Open  "SELECT @@identity as cou" , CurrentProject.Connection
переменная = rs!cou
rs.Close

Однако и этот способ имеет ограничения, а именно:
работает только через ADO и только в Jet 4 и позже;

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

Thanx 2 Хам, Лох, Виг!
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32320454
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
В свете последних веяний вношу поправку. Оказывается, если описать нечто As New, то потом нельзя превратить его в Nothing. Поэтому превращаю

Dim rs As New ADODB.Recordset

в

Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32323583
Fagrant
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я тут пытался играть с аттрибутами поля (.Attributes), по идее комбинируя их можно получить нечто вроде автоинкрементированного поля, но с возможностью редактирования. И наоборот :) Но мне не удалось достичь нужного результата, возможно что-то упустил, башка не в ту сторону думает ;(
Что скажут мэтры? Такое невозможно в принципе? Тогда нафига эти аттрибуты созданы?
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32323588
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
По-моему, есть стандартный набор типов полей, из которого вылезть нельзя. Атрибуты сделаны для того, чтобы либо создать поле разрешенного типа, либо узнать тип существующего поля.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32323921
VikingTor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ладно... все замммммечательно с этими каунтерами...
Тока вот вопрос - а как все это будет работать если к таблице с таким каунтером применить INSERT INTO...SELECT... - добавление нескольких записей одним запросом?
Не будет ли так, что все добавляемые записи будут пытаться брать одновременно одно и то же значение доморощенного каунтера? А?
Спрашиваю, потому что лень проверить
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32323949
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блин, уже начал кипятком писать по поводу "лень проверить", но вовремя поглядел на приведенный кусок кода.

Саныч, если в функцию ничего не передавать - она будет вызываться только один раз . Поэтому надо туда передавать хоть что-то, например так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Function MyFun(varDummy As Variant, Optional iStartValue As Variant) As Long
Static n As Long
If IsMissing(iStartValue) Then
    MyFun = n
    n = n +  1 
Else
    n = iStartValue
    MyFun = True
End If
End Function

В запросе обращаемся к ней дважды:
в части WHERE - с параметрами (чтоугодно,N), где N равно нужному начальному значению счетчика;

в части SELECT - в качестве первого параметра передавать любое поле из таблицы, второй параметр не указывать.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32324731
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
2 VikingTor:

Немножко не понял вопрос. Таблица с обычным каунтером, а инсерт с обычными данными? Или кто-то из них с каким-то из приемов, описанных выше?

2 Лох:

А тебя зато понял. :^) Да, надо будет дать твой вариант кода вместо моего и дать к нему пояснение, почему его нельзя упрощать.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32325161
(c)VIG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир Саныч писал:В свете последних веяний вношу поправку. Оказывается, если описать нечто As New, то потом нельзя превратить его в Nothing.
А вот с этого места пожалуйста поподробнее .
Что за новые веяния?Почему не знаю?И почему у меня превращает?Что я делаю неправильно?
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32325163
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VIG, не нервничай, можно
Set чтототам = Nothing превратит что-то там в Nothing
Но при первом же действии с чтототам (даже при таком элементарном как чтототам Is Nothing) оно создается заново. Так что лучше так не писать.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32325171
(c)VIG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Но при первом же действии с чтототам (даже при таком элементарном как чтототам Is Nothing) оно создается заново.
Ну,ПРО ЭТО я знаю...
Я ,то грешным делом подумал,что вышел новый указ кнессета/Гос.думы/модераторов ,запрещающий использование dim чтототам as new .
"Теперь я спокоен,чего мне бояться ..." (В.Высоцкий)
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32327817
Данил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго вам, сограждане!
Никто, кстати, не сталкивался с таким траблом?
Если у вас ленточная форма / Access97, то самопальный счетчик выдает max, если поле видно на экране, и max+1 (что и требуется), если записей много и оно уже ушло из "зоны видимости"
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32327822
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Это смотря что понимается под самопальным счетчиком. Их только в этим топике несколько разных.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32333921
Фотография Лифчик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Q: Счетчик показывает, что последняя запись в моей таблице имеет номер N, а реально записей M, где M<N. Почему счетчик не правильно считает количество записей в таблице? Что это - баг или фича?

А: Счетчик не должен подсчитывать количество актуальных записей в Вашей таблице. Его назначение совсем другое. Прочитай этот фак целиком и тебе все будет понятно.

ЗЫ Ясно, что вопрос перекликается с вопросом про дырки, но мне кажется, что надо жирно выделенное как-то пометить.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32333938
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Я бы выделил жирным примечание в конце. :^)
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32366152
Фотография Geo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не стал заводить отдельный топик, т.к. мой вопрос вроде бы пересекается с этим. Сорри, если что.

Есть задача: сделать автоматическу нумерацию документов в пределах, скажем, месяца, без "закрытия периода" и без "архивных табличек". Конечно, нормальный счетчик, обслуживаемый акцессом, в таблице есть, для связей и т.п. Но нужна нумерация документов - та, что видна пользователю и печатается в выходных формах. Причем в пределах месяца разные пользователи не должны одновременно получить (то, что они сами могут поставить, вопрос другой) два одинаковых номера. Где-то в начале этого топика я предлагал довольно идиотский способ. Теперь я его же попробовал сделать. Вот что получилось:

В "серверной" базе держим запись с последним номером. Очередной пользователь увеличивает ее содержимое и пользуется полученным значением.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
  Dim rs As DAO.Recordset
  Dim rsLocal As DAO.Recordset
  Dim t As Long
  
  Set rs = CurrentDb.OpenRecordset( "mycounters" , dbOpenDynaset)
  Set rsLocal = CurrentDb.OpenRecordset( "testcounters" , dbOpenDynaset)
  
  Do While True
    On Error Resume Next
    Do
      Err.Clear
      rs.Edit
      t = rs!mycounter
      t = t +  1 
      rs!mycounter = t
      rs.Update
    Loop While Err.Number
    On Error GoTo  0 
    rsLocal.AddNew
    rsLocal!testcounter = t
    rsLocal.Update
    Me.Поле1 = t
    Me.Repaint
  Loop


Попробовал двумя параллельными сеансами. Насоздавалась куча записей. Повторов нету.

Плюсы - можно генерить уникальные значения в пределах периода без пересоздавания таблицы.
...
Рейтинг: 0 / 0
25 сообщений из 176, страница 4 из 8
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / FAQ. Что мы знаем про каунтеры (aka счетчики)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]