powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / интересные факты / наблюдения / анализ чужих и собственных решений
280 сообщений из 280, показаны все 12 страниц
интересные факты / наблюдения / анализ чужих и собственных решений
    #37098130
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотел бы поделиться с некоторыми своими наблюдениями, обнаруженными фактами. Хотелось бы осуществить что-то вроде «обмен мнений».
В и-нете много нестандартных решений казалось бы на первый взгляд «нереальных» задач. Когда начинаешь анализировать коды, то иной раз голова идёт кругом от длинного листинга, а чтобы разобраться иной раз необходимо потратить длительное время. Но разбираться в коде хочется.

Хочу начать с запросов.

Есть в этом форуме несколько интересных топиков о запросах. Вот некоторые из них:
- Самоправка запроса
- access сам меняет запрос
- Социологическое исследование: Как народ хранит запросы?
и т.д., и т.д.

Этот список можно продолжать достаточно долго.
А собственно, почему так происходит, почему Access самопроизвольно меняет SQL текстовку запроса?
На сей счёт у меня появилась версия-гипотеза. Я, конечно, не уверен в том, что мои догадки верны, хочу обсуждать с уважаемым гуру! Я считаю главной причиной «всех бед» это системная таблица « MSysQueries »! Кстати, есть интересная статейка, где как раз описываются некоторые детали данной таблицы: Как достать SQL запрос из *.mdb без MS Access
Чтобы правильнее объяснить то, что я имею ввиду, пожалуй, следует произвести следующий эксперимент:
Создаём простой запрос и назовем «Query1»
Код: plaintext
SELECT * FROM Table1;
Теперь создаём ещё один запрос «Query2», который будет ссылаться на наш 1-запрос.
Код: plaintext
SELECT * FROM Query1;

Далее, вручную поменяем название 1-запроса как «Q1».
С помощью VBA смотрим текст запроса «Query2».
Код: plaintext
Sub TestQuerySQL()\n    Dim Qry As DAO.QueryDef\n    Set Qry = CurrentDb.QueryDefs("Query2")\n    Debug.Print Qry.SQL\n    Set Qry = Nothing\nEnd Sub

SQL текст запроса не изменился, хотя мы название 1-запроса поменяли.
А теперь откроем запрос «Query2» в режиме таблицы (можно вручную, а можно программно открывать, эффект – одинаковый). Access не будет ругаться, что не может найти «Query1». Ещё раз запустим процедуру TestQuerySQL.
Вуаля! В SQL тексте запроса «Query1» исчез, вместо него «Q1».
А как это произошло? Именно благодаря системной таблице «MSysQueries»! Помимо системных таблиц видимо Access где-то «запоминает» старое и новое название объекта после переименования. А перед открытием запроса, скорее всего перепроверяет не изменились ли названия объектов, которых использует данный запрос. Если да, то автоматически сам же подправляет. Вообщем-то всё это скорее сделано для «начинающих» пользователей, которые могут изменить названия объектов базы, но при этом могут и забыть подправить запросы.
Системная таблица «MSysQueries» разбивает запросы на поля и это означает, что не только название таблиц и запросов, используемые внутри определённого запроса, но и название полей имеет тот же эффект. Т.е. пусть «Таблица1» имеет поле «Поле1». Пишем такой простой запрос «Запрос1»:
Код: plaintext
SELECT Поле1 FROM Таблица1;
Теперь открываем «Таблица1» в режиме конструктора и поменяем название поля на «П1». После этого попробуем открыть «Запрос1» и как мы можем убедиться название поля в запросе автоматически поменялся на «П1», хотя мы запрос не корректировали.

Но не все запросы имеют такой эффект. А именно следующие виды запросов в системной таблице «MSysQueries» вообще не разбиваются на отдельные поля:
- запрос на объединение;
- запрос к серверу
- запрос на управление
- вложенный (внутренний) и подчинённый запрос.

«Запрос1» перепишем следующим образом:
Код: plaintext
SELECT *\nFROM (SELECT П1 FROM Таблица1) AS Data;
Теперь открываем «Таблица1» в режиме конструктора и возвращаем предыдущее название поля «Поле1».
А вот теперь «Запрос1» у нас не будет работать правильно. Если откроете его, то Access воспримет «П1» как параметр, а не как название поля!

Видать не с проста Microsoft такие виды запросов как «Объединение», «К серверу», «Управление» отделил в своем интерфейсе отдельно как «Запрос SQL». Так как ими в основном пользуются не новички, а продвинутые пользователи, то и автоматическая корректировка посчитали излишней.
Итак, почему же Access самопроизвольно меняет SQL текстовку запроса? Потому что так Accessу более удобнее зафиксировать поля в системной таблице «MSysQueries». Здесь не хотелось бы использовать термин «оптимизатор запросов», ибо здесь не идёт в буквальном смысле оптимизация запросов, а скорее всего происходит «помощь чайникам». Может я сильно ошибаюсь по поводу полного отсутствия оптимизации, может и в правду хоть что-то Access наподобие SQL Server оптимизирует. Но очень часто после такой «оптимизации» сложные фильтры запроса получаются чересчур замудрёнными и порой некорректными. С одного раза даже и не понятно, что и как же запрос фильтрует.

Здесь также хочу отметить, почему же вложенных запросов Access 2003 и ранние версии отмечает внутри квадратных скобок. Дело в том, что когда Вы во внутри запроса соединяете более двух таблиц / запросов через INNER, LEFT, RIGHT JOIN, то отдельные части Access заключает в обычные скобки и всё, что находится во внутри этих обычных скобок Access разбивает и размещает у себя в таблице «MSysQueries». А вот когда Accessу как бы «нет необходимости» в разбивке (т.е. случай с вложенным запросом), то для «своего удобства» отмечает эту часть SQL текста особым образом. Ну и здесь есть косяк: так сказать «оптимизатор запросов» (который «оптимизирует» SQL текст запроса для размещения в таблице «MSysQueries») видимо сначала анализирует текст и отмечает ту часть, которую не надо разбивать, квадратными скобками. Ну а если уже в тексте есть оные, то тут разработчики видимо толком не объяснили «оптимизатору» как анализировать такие тексты. Т.к. «оптимизатор» не знает, что делать, то и предпочитает ругаться.
Но начиная с Access 2007 слегка такой «порядок вещей» был изменён разработчиками. Теперь «оптимизатор» не пишет квадратные скобки в SQL тексте, а держит «в уме» в момент фиксации SQL текста в системной таблице «MSysQueries». А когда кто-то изменит запрос, то и «оптимизатору» нечего ругаться, ибо в тексте изначально нет квадратных скобок.

P.S.
Надеюсь, народ начнёт критиковать мой топик и спорить. Как известно в спорах рождается истина.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37098154
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как оптимизировать запросы?

Как известно, существуют проверенные со временем старинные «лекарства», позволяющие повысить быстродействие запросов. Вот некоторые из них:
- по возможности вместо «HAVING» использовать «WHERE». Иногда требуется фильтровать данные после групповых функций таких как «MIN», «MAX», «AVG» и т.д. В таких случаях, увы фильтровать данные с помощью «WHERE» нельзя, придётся использовать «HAVING». А в остальных случаях нецелесообразно использование «HAVING».
- по возможности не использовать статистических функций по подмножеству, таких как Dsum, Dcount и т.д. В некоторых случаях если требуется обновляемость запроса, то приходится использовать подобные функции.
- по возможности не использовать подчинённые запросы на стороне «WHERE» или «HAVING». Иногда бизнес логика все же требует использование подчинённых запросов.
- если нет необходимости сортировки, то не применять ORDER BY.
Помимо этих способов Microsoft рекомендует:
- по чаще сжимать базу;
- использовать индексацию полей и т.д., и т.п.
Всем всё это известно. Ничего нового. А вот про IIF почти ни слова!
Что мы знаем про IIF? Если открыть справочник Access 2003, то там написано следующее:
Функция IIf всегда вычисляет и truepart, и falsepart, хотя возвращает только одно из них. Из-за этого могут возникнуть нежелательные побочные эффекты. Например, если в falsepart произошла ошибка при делении на ноль, эта ошибка возникнет, даже если выражение будет оценено как True.
Все эти слова оказались справедливы только для VBA, а вот для JET они не справедливы! Недавно Sator Arepo предоставил наиубедительнейший пример в другом топике.
Код: plaintext
select iif(true,\'ok\' , 1 / 0 ) as test
и
Код: plaintext
select iif(false,\'ok\' , 1 / 0 ) as test

Из этого следует одна очень полезная фитча:
Если в фильтре WHERE использованы несколько условий AND и OR, то вместо них можно использовать IIF и тогда запрос будет работать чуть быстрее.
Пример:
Вместо следующих условий
Код: plaintext
WHERE Field1 >  1  AND Field2 <  1000  AND Field3 BETWEEN  1  TO  100 
Можно написать так
Код: plaintext
WHERE\nIIf(Field1 <=  1 , False,\nIIf(Field2 >=  1000 , False,\nIIf(Field3 >  100 , False\nIIf(Field3 <  1 , False, True))))
2-вариант с IIf работает быстрее, т.к. при первом же невыполнения условия «Field1 > 1» Access не станет проверять остальные условия и тем самым экономит время! Именно поэтому и в MS SQL Server ряд исследователей рекомендуют использование CASE WHEN … THEN … В Access аналог CASE WHEN это IIF.
При этом рекомендуется расположить условия наибольшего отбора выше по веткам IIF, тогда запрос станет наиболее оптимальным.
Условия отбора AND в IIF надо писать с точностью до наоборот, т.е. если Вам нужно условие Field1 > 1, то следует писать IIf(Field1 <= 1, False, а в самом конце True (как указано в примере). А вот условие OR придётся писать через = примерно так:
Допустим требуется фильтровать данные по следующим условиям:
Код: plaintext
WHERE Field1 =  1  OR Field2 =  2  OR Field3 =  3 
Чтобы перевести на IIF следует писать так:
Код: plaintext
WHERE\nIIf(Field1 =  1 , True,\nIIf(Field2 =  2 , True,\nIIf(Field3 =  3 , True, False)))

Функция IIF имеет ещё одно преимущество:
Если использовать достаточно сложные условия отбора, то после сохранения запроса так сказать «оптимизатор» самопроизвольно «подтасует» условия так, как ему удобно (см. мой пост выше). А вот в случае IIF порядок проверки условий гарантированно не будет изменен «оптимизатором».
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37103379
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Иногда бывает полезным установить CHECK CONTRSTRAINT к определенной таблице, который может сверять данные одной таблицы с другой. Для этого вовсе не обязательно включать опцию " Синтаксис для SQL Server (ANSI 92) ". Но в этом случае придётся установить его программно. Пример:
Допустим, у нас есть таблица "Контракт", где есть поле "КодКонтракта" и "Сумма", а также есть таблица "Спецификация", где есть поля: "КодКонтракта", "КодТовара", "Цена", "Количество". Если умножить "Цена" и "Количество" товара, то получим стоимость одной позиции товара. Предположим нам нужно установить ограничение: общая сумма всех позиций по одному контракту не должна превышать сумму контракта. Как это сделать?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Sub SetCheckConstraint()
    Dim strSQL AS String

    strSQL = "ALTER TABLE Контракт ADD CONSTRAINT СверкаСуммы CHECK " & _
        "((Контракт.Сумма >= (SELECT SUM(Цена*Количество) FROM Спецификация AS S " & _
        "WHERE S.КодКонтракта = Контракт.КодКонтракта)));"
    CurrentProject.Connection.Execute strSQL
End Sub

Ну и чтобы удалить ограничение нужно запустить такой код:
Код: plaintext
1.
2.
3.
4.
5.
Sub DeleteConstraint()
    Dim strSQL AS String

    strSQL = "ALTER TABLE Контракт DROP CONSTRAINT СверкаСуммы"
    CurrentProject.Connection.Execute strSQL
End Sub

P.S. Ну а вообще конечно лучше использовать VBA функции, чтобы получить больше возможностей (Триггер Бенедикта). Я вышеуказанными примерами лишь подчеркнул, что включение опции " Синтаксис для SQL Server (ANSI 92) " вовсе не обязательное и как видите кириллица (по крайнем мере в А2003) проходит без проблем.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37103391
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

А вот это уже интересно. Только насколько это оптимальнее чем другие способы (доп. поле в запросе(форме), рекордсет через подобную sql-строку, Dsum и т.д.)?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37103397
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvk,

Вы на уровне базы устанавливаете ограничение. Кто-нибудь даже если создаст линкованную таблицу в "чужой базе" и попытается внести "неправильные" изменения, то уже не сможет.
Правда есть маленький нюанс: предметное "ругательство" (наподобие Validation Text) не возможно установить. Для этого ИМХО триггер Бенедикта лучче!
Кстати, удаление таблицы также невозможно до тех пор, пока существует CONSTRAINT.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37103465
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

1. Тоесть сообщение выдать нельзя никакое? А разве здесь error не обрабатывается?(?)
2. Что касается удаления - пофиг, кто интересно свои рабочие таблицы с данными
удаляет? Только маньяк какой-нибудь..
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37122139
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересные факты.
Всем известно, что любой запрос в MS Access может иметь максимум 255 полей.
А вот в запросах на объединение (UNION) ограничение иное:
Общее количество полей каждого блока запроса в сумме не должно превышать 255!
Т.е. если 1-блок запроса содержит 128 полей и 2-блок запроса также имеет 128 полей, то Access будет ругаться, т.к. 128+128=256 (больше 255)!!!

Пример (этот запрос не пройдёт):
Код: 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.
SELECT  1  AS F1,  2  AS F2,  3  AS F3,  4  AS F4,  5  AS F5,  6  AS F6,  7  AS F7,  8  AS F8,  9  AS F9,  10  AS F10,
 11  AS F11,  12  AS F12,  13  AS F13,  14  AS F14,  15  AS F15,  16  AS F16,  17  AS F17,  18  AS F18,  19  AS F19,  20  AS F20,
 21  AS F21,  22  AS F22,  23  AS F23,  24  AS F24,  25  AS F25,  26  AS F26,  27  AS F27,  28  AS F28,  29  AS F29,
 30  AS F30,  31  AS F31,  32  AS F32,  33  AS F33,  34  AS F34,  35  AS F35,  36  AS F36,  37  AS F37,  38  AS F38,  39  AS F39,
 40  AS F40,  41  AS F41,  42  AS F42,  43  AS F43,  44  AS F44,  45  AS F45,  46  AS F46,  47  AS F47,  48  AS F48,  49  AS F49,
 50  AS F50,  51  AS F51,  52  AS F52,  53  AS F53,  54  AS F54,  55  AS F55,  56  AS F56,  57  AS F57,  58  AS F58,  59  AS F59,
 60  AS F60,  61  AS F61,  62  AS F62,  63  AS F63,  64  AS F64,  65  AS F65,  66  AS F66,  67  AS F67,  68  AS F68,  69  AS F69,
 70  AS F70,  71  AS F71,  72  AS F72,  73  AS F73,  74  AS F74,  75  AS F75,  76  AS F76,  77  AS F77,  78  AS F78,  79  AS F79,
 80  AS F80,  81  AS F81,  82  AS F82,  83  AS F83,  84  AS F84,  85  AS F85,  86  AS F86,  87  AS F87,  88  AS F88,  89  AS F89,
 90  AS F90,  91  AS F91,  92  AS F92,  93  AS F93,  94  AS F94,  95  AS F95,  96  AS F96,  97  AS F97,  98  AS F98,  99  AS F99,  100  AS F100,
 101  AS F101,  102  AS F102,  103  AS F103,  104  AS F104,  105  AS F105,  106  AS F106,  107  AS F107,  108  AS F108,  109  AS F109,
 110  AS F110,  111  AS F111,  112  AS F112,  113  AS F113,  114  AS F114,  115  AS F115,  116  AS F116,  117  AS F117,  118  AS F118,  119  AS F119,
 120  AS F120,  121  AS F121,  122  AS F122,  123  AS F123,  124  AS F124,  125  AS F125,  126  AS F126,  127  AS F127,  128  AS F128
FROM MSysObjects;

UNION ALL SELECT  1  AS F1,  2  AS F2,  3  AS F3,  4  AS F4,  5  AS F5,  6  AS F6,  7  AS F7,  8  AS F8,  9  AS F9,  10  AS F10,
 11  AS F11,  12  AS F12,  13  AS F13,  14  AS F14,  15  AS F15,  16  AS F16,  17  AS F17,  18  AS F18,  19  AS F19,  20  AS F20,
 21  AS F21,  22  AS F22,  23  AS F23,  24  AS F24,  25  AS F25,  26  AS F26,  27  AS F27,  28  AS F28,  29  AS F29,
 30  AS F30,  31  AS F31,  32  AS F32,  33  AS F33,  34  AS F34,  35  AS F35,  36  AS F36,  37  AS F37,  38  AS F38,  39  AS F39,
 40  AS F40,  41  AS F41,  42  AS F42,  43  AS F43,  44  AS F44,  45  AS F45,  46  AS F46,  47  AS F47,  48  AS F48,  49  AS F49,
 50  AS F50,  51  AS F51,  52  AS F52,  53  AS F53,  54  AS F54,  55  AS F55,  56  AS F56,  57  AS F57,  58  AS F58,  59  AS F59,
 60  AS F60,  61  AS F61,  62  AS F62,  63  AS F63,  64  AS F64,  65  AS F65,  66  AS F66,  67  AS F67,  68  AS F68,  69  AS F69,
 70  AS F70,  71  AS F71,  72  AS F72,  73  AS F73,  74  AS F74,  75  AS F75,  76  AS F76,  77  AS F77,  78  AS F78,  79  AS F79,
 80  AS F80,  81  AS F81,  82  AS F82,  83  AS F83,  84  AS F84,  85  AS F85,  86  AS F86,  87  AS F87,  88  AS F88,  89  AS F89,
 90  AS F90,  91  AS F91,  92  AS F92,  93  AS F93,  94  AS F94,  95  AS F95,  96  AS F96,  97  AS F97,  98  AS F98,  99  AS F99,  100  AS F100,
 101  AS F101,  102  AS F102,  103  AS F103,  104  AS F104,  105  AS F105,  106  AS F106,  107  AS F107,  108  AS F108,  109  AS F109,
 110  AS F110,  111  AS F111,  112  AS F112,  113  AS F113,  114  AS F114,  115  AS F115,  116  AS F116,  117  AS F117,  118  AS F118,  119  AS F119,
 120  AS F120,  121  AS F121,  122  AS F122,  123  AS F123,  124  AS F124,  125  AS F125,  126  AS F126,  127  AS F127,  128  AS F128
FROM MSysObjects;
А вот если уберете 128-поле, то Access нормально воспримет запрос. Переключение на "Синтаксис для SQL Server (ANSI 92)" не спасёт, результат тот же.

Если в запросе на объединение имеется поле МЕМО, где имеется значение больше 255 символов, то Access вернет только первые 255 символов.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37122303
Guest33
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторЕсли в запросе на объединение имеется поле МЕМО, где имеется значение больше 255 символов, то Access вернет только первые 255 символов.
Расшифруйте, пожалуйста. По моим наблюдениям, если в 1-й запрос включить мемо поле, то запрос с юнионом не режет длину строки.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37122306
полином
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenИнтересные факты.

о! сколько нам открытий чудных... (с)

studierenОбщее количество полей каждого блока запроса в сумме не должно превышать 255!


формулировочка
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37122389
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Guest33авторЕсли в запросе на объединение имеется поле МЕМО, где имеется значение больше 255 символов, то Access вернет только первые 255 символов.
Расшифруйте, пожалуйста. По моим наблюдениям, если в 1-й запрос включить мемо поле, то запрос с юнионом не режет длину строки.

Прошу прощения, что не уточнил деталь:
- если используете UNION ALL, то Access не режит.
- а вот если просто UNION, то Access покажет только первые 255 символов!

Вот теперь кажется описал полностью!

полиномstudierenОбщее количество полей каждого блока запроса в сумме не должно превышать 255!


формулировочка

Ну хорошо, может быть написано не совсем правильно. Ну мысль я надеюсь Вы правильно поняли?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37122986
полином
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenНу мысль я надеюсь Вы правильно поняли?

не с первого раза :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123220
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то про особенность ограничения 255 полей в запросах на объединение решил здесь написать после того, как прочёл топик Too many fields defined.
В этом топике есть такой запрос:
Код: plaintext
SELECT Part_all, id, start_date, end_date, Description, Manager\nFROM [\nSELECT *,Part_M1 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M2 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M3 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M4 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M5 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M6 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M7 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M8 as Part_all FROM Main_Table \nUNION \nSELECT *,Part_M9 as Part_all FROM Main_Table \nUNION\nSELECT *,Part_M10 as Part_all FROM Main_Table ]\nWHERE (end_date>=Date()) and (Part_all<>\'\')\nORDER BY Part_all;

Автор также сообщает, что "в главной таблице 83 поля". Как мы видим в каждом блоке запросов есть дополнительное поле "Part_all", стало быть каждый блок имеет 84 поля. Всего блоков 10, в итоге мы имеем 84*10=840. А это гораздо больше чем 255!!!! Вот именно поэтому и Access ругается " Too many fields defined ".

Вывод: в запросах на объединение нежелательно использовать "*", лучше явно указать только необходимые поля!

В том топике есть ссылка на интересный сайт, где имеется вот такая информация:
Tables: "Too many fields defined" error message
(Q) When I try to save a table, I keep getting the error message "Too many fields defined". What\'s causing this to come up?
(A) Access keeps an internal count of total number of fields in a table and has a limit of 255 fields per table. Each time you modify a field or add a field, this count increases by 1. When you delete a field, Access does NOT reset this counter. So it\'s possible for you to have less than 255 fields and still get this error message.
If your field count is less than 255, just compact the database again which should reset the internal field count counter.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123254
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

неплохо было бы вам проштудировать давний топик ФАК: А знаете ли вы, что... и то, чего там не хватает, добавить. В одном месте хранить все. Желательно было бы.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123282
8060
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren, относительно количества полей в UNION можно посмотреть в этом и следующем за ним постах.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123289
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mds_world,

Не знал, что есть топик "А знаете ли Вы ..." :))

И что в результате? Опять закроют мой топик? Если это так, то жаль! :((
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123293
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
8060studieren, относительно количества полей в UNION можно посмотреть в этом и следующем за ним постах.

Спасибо за ссылку!
Значит я ошибся. Бывает.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123306
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenmds_world,

Не знал, что есть топик "А знаете ли Вы ..." :))

И что в результате? Опять закроют мой топик ? Если это так, то жаль! :((
Вовсе нет! Я, во всяком случае этого делать не собираюсь.

Вопрос ведь иначе ставится - в аксе есть много различных особенностей, подмеченных разными авторами. Желающему программировать в этой среде полезно их знать. Но поиск затруднителен. Хотя бы потому, что не знаешь, что искать. А когда все собрано в одном месте удобно.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123543
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mds_world,

Есть "золотые топики". Они одни, слово "золотые" встречается крайне редко на форуме.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123942
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А2003

Странную вещЧ я сейчас обнаружил.
Допустим есть такой запрос
Код: plaintext
SELECT * FROM Table1

Можно его переписать вот так
Код: plaintext
TABLE Table1
После сохранения запроса текст вернётся к 1-варианту. Об этом написано в "ФАК: А знаете ли вы, что... ". Все нормально, всё О.К. Но обнаружил и такую странность. Можно этот же запрос переписать вот так:
Код: plaintext
1.
SELECT *
FROM [TABLE Table1]. AS X;
Обратите внимание: здесь использована квадратная скобка [ ]. . Запрос можно сохранить и Access не ругается. А вот если заменить квадратную скобку на обычную скобку, тут уж Access начинает кричать!!! Все время боролся с квадратными скобками во вложенных запросах, а теперь на тебе Access требует их!!!

Продолжил эксперимент и написал вот такой запрос:
Код: plaintext
1.
2.
SELECT *
FROM [PARAMETERS x Long;
SELECT * FROM MSysObjects AS O WHERE Id = x]. AS Data;

Обычно Access не терпит PARAMETERS во вложенных запросах. А здесь парадокс - пашет как надо! И здесь квадратные скобки никак нельзя заменить на обычные скобки!

P.S. Смотрю на всё это и диву дивлюсь: сколько же ещё секреты спрятаны за семью замками.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37123997
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просьба тем, у кого есть А2007 или А2010: не могли бы протестировать вот эти запросы? К сожалению у меня в наличии нет таких версий под рукой.
Код: plaintext
TABLE Table1
Код: plaintext
1.
SELECT *
FROM [TABLE Table1]. AS X;
Код: plaintext
1.
2.
SELECT *
FROM [PARAMETERS x Long;
SELECT * FROM MSysObjects AS O WHERE Id = x]. AS Data;
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37124012
П-Л
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уже достаточно причин для ухода с MDB в ADP
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37124042
8060
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenСтранную вещЧ я сейчас обнаружил.
Вот здесь пример "странного" запроса без всяких наворотов (в двух постах ниже эта "странность" обсуждается).
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37124199
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
П-ЛУже достаточно причин для ухода с MDB в ADP

У меня пока нет ни одной, кроме личного интереса. А будущий переход на акс2010 разве это позволит сделать?

p.s. извиняюсь за оффтопик.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37127461
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если в А2007 написать вот такой запрос в режиме SQL и затем открыть его в режиме таблицы, то запрос работает:
Код: plaintext
1.
2.
SELECT *
FROM [PARAMETERS x Long;
SELECT * FROM MSysObjects AS O WHERE Id = x]. AS Data;

Но!!! Если сохранить запрос, то Access текст SQL меняет до неузнаваемости!
Код: plaintext
1.
SELECT *
FROM (PARAMETERS x Long)  AS Data;
И естественно НЕ РАБОТАЕТ после этого запрос!
Да!!! Дела!!!
В А2010 не смог экспериментировать из-за не имения, но подозреваю, что там дела обстоят аналогично.

Попробовал экспериментировать с перекрестным запросом в А2007:
Код: plaintext
1.
2.
3.
4.
5.
6.
SELECT *
FROM [TRANSFORM SUM(S.Quantity) AS Total
SELECT S.SaleDate
FROM tblSale AS S INNER JOIN tblProduct AS P ON S.ProductID=P.ProductID
WHERE S.SaleDate>=# 1 / 1 / 2011 #
GROUP BY S.SaleDate
PIVOT P.Product IN ('Товар№1', 'Товар№2', 'Товар№3')].  AS Sale;
Вот так в А2007 можно сохранить запрос. Все работает вроде нормально. Но!!! Теперь А2007 после сохранения запроса меняет автоматически квадратные скобки на обычные. А вот если попробовать что-то изменить, теперь ругается. Нужно каждый раз вернуть квадратные скобки вместо обычных. Т.е. всё происходит с точностью до наоборот.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37127493
Фотография mds_world
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

посмотрите: Самоправка запроса
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37132939
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во всех продуктах Microsoft Office можно закрыть текущий пользовательский объект нажатием клавиши Ctrl+W. В MS Access также работает данное сочетание клавиши (например, если хотим закрыть открытую таблицу, запрос, форму и т.д.). Но вот в режиме "Runtime", увы, не работает. Пришлось создать макрос "AUTOKEYS", где в столбце "Имя макроса" (Macro Name) ввел ^w , а в столбце "Макрокоманда" (Action) - Закрыть (в английских версиях - Close ) и при этом свойства данной команды "Тип объекта" и "Имя объекта" оставил пустыми, чтобы макрос сработал на все виды объектов БД. Что интересно, даже если мы работаем в русской раскладке клавиатуры, то при нажатии Ctrl+ц (w получается как ц), то макрос все равно реагирует.

Может быть у кого-нибудь есть иное решение как в режиме "Runtime" заставить работать сочетание клавиш Ctrl+W без макроса?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37132960
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren, Ctrl+F4?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37132967
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindstudieren, Ctrl+F4?

Спасибо, так тоже работает. :)
А вот почему не работает Ctrl+w в чистом виде в Runtime, это загадка разработчиков.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37132996
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren, :) Может быть, Ctrl+W они оставили за другой комбинацией или вообще забыли?

Хотел написать своё наблюдение. Когда открываете редактор VBA, вы автоматически попадаете в последний из добавленных модулей (или модулей форм). Всегда один и тот же, если не добавляли новых. Это к топику: Сохранение позиции в модуле .
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37133014
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMind,

Проверил на всех проектах, действительно первом делом попадаем в последний из добавленных модулей. Не обращал на это внимание, теперь буду знать. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37156658
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как запретить ввод определенных символов в контролах формы?

Я случайно наткнулся на такой простой, но оригинальный код. Может быть кому-то пригодится:
Код: plaintext
1.
2.
3.
4.
5.
Private Sub txtMyTextBox_KeyPress(KeyAscii As Integer) 
    Dim strTemplate As String 

    strTemplate = "!@#$%^&*()_+="
    If InStr( 1 , strTemplate, Chr(KeyAscii)) >  0  Then KeyAscii =  0  
End Sub

Если юзер попробует ввести любой символ из шаблона "!@#$%^&*()_+=", то контрол формы просто будет игнорировать.


Источник: Hayder Access
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37156667
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindstudieren, Ctrl+F4?

Небольшая поправочка:
С помощью Ctrl+F4 можно закрыть любой активный объект базы точно также как и Ctrl+W.
Но чисто экспериментально обнаружил, что если свойство формы "Всплывающее окно" (PopUp) имеет значение True, то с помощью Ctrl+F4 невозможно закрыть форму.

А вот если форма - модальное окно (т.е. свойство "Modal = True"), то с помощью Ctrl+F4 можно закрыть её.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37159663
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Функция Format для параметра Null, в отличие от некоторых стандартных функций, возвращает не Null, а "". Из-за этого невозможно корректно обработать случай
Код: plaintext
1.
s = ("от " + Format(vDate, "dd\.mm\.yyyy")) & ""
(появится слово "от ").
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37159681
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощения, способ таков:
Код: plaintext
1.
Format(vDate, "от dd\.mm\.yyyy")
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37159834
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindФункция Format для параметра Null, в отличие от некоторых стандартных функций, возвращает не Null, а "". Из-за этого невозможно корректно обработать случай
Код: plaintext
1.
s = ("от " + Format(vDate, "dd\.mm\.yyyy")) & ""
(появится слово "от ").

Как для VBA, так и для JET SQL данное утверждение справедливо.
Код: plaintext
1.
2.
3.
4.
SELECT
     "от " + Format(Null, "dd\.mm\.yyyy"),
     Format(Null, "от dd\.mm\.yyyy"),
     "от " + Format(# 1 / 1 / 2011 #, "dd\.mm\.yyyy"),
     Format(# 1 / 1 / 2011 #, "от dd\.mm\.yyyy");

Спасибки. :))
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37166457
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как получить набор записей (Recordset) от запроса с параметрами?

Допустим у нас есть "Запрос1", у которого 2 параметра "Число", "Дата".
С помощью DAO набор записей можно получить так:
Код: plaintext
1.
2.
3.
4.
5.
6.
Dim xQuery AS DAO.Querydef
Dim RecSet AS DAO.RecordSet

SET xQuery = CurrentDB("Запрос1")
xQuery.Parameters("Число") =  1 
xQuery.Parameters("Дата") = # 1 / 1 / 2010 #
SET RecSet = xQuery.Openrecordset

Чтобы сократить код можно вообще обойтись и без Querydef.
Код: plaintext
1.
2.
3.
4.
5.
Dim RecSet As DAO.Recordset
Dim strSQL As String

strSQL = "PARAMETERS Число Long = 1, Дата Datetime = #1/1/2010#;" & vbCrLf & _
    "TABLE (Запрос1)"
Set RecSet = CurrentDb.OpenRecordset(strSQL)

Здесь вместо ключевого слово "PARAMETERS" можно использовать "PROCEDURE". Эффект будет одинаковым.
При этом название, тип и значение параметров запроса должны быть ПОЛНОСТЬЮ указаны после ключевого слова "PARAMETERS" (или "PROCEDURE"). Так если запрос имеет 3 параметра, а мы указали только 2, то Access будет ругаться.
Вместо "TABLE (Запрос1)" можно использовать более традиционное выражение "SELECT * FROM Запрос1".

А вот в случае с ADODB синтаксис будет другой, больше похож на синтаксис MS SQL Server.
Код: plaintext
1.
2.
3.
4.
5.
Dim RecSet As ADODB.Recordset
Dim strSQL As String

strSQL = "EXECUTE Запрос1 @Число=1, @Дата=#1/1/2011#;"
Set RecSet = New ADODB.Recordset
RecSet.Open strSQL, CurrentProject.Connection, adOpenKeyset

Здесь как Вы видите нужно перед названием параметра обязательно добавить "@" (в стиле MS SQL Server), иначе Access будет ругаться.
В принципе можно и пропустить название параметров, в этом случае следует строго соблюдать последовательность параметров.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37190520
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Недавно обнаружил, что в запросах можно получить значение свойств некоторых объектов VBA (не все свойства конечно, но кое-что можно!).
Вот примерчик:
Код: plaintext
1.
2.
3.
4.
5.
SELECT
    CurrentDB.Name AS DBFullName,
    CurrentProject.Name AS DBName,
    Currentproject.Path AS DBPath,
    Currentproject.AccessConnection AS AccessConnection,
    Currentproject.BaseConnectionString AS Connection;

Можно оказывается получить и "длинные" свойства, т.е. чтобы добраться до нужного свойства приходится "беспокоить" несколько объектов, типа так:
Код: plaintext
SELECT CDate(CurrentProject.AllForms!Форма1.DateModified) AS DateModified

При этом если нам необходимо использовать скобки, кавычки или апострофы для того, чтобы добраться до свойство объекта, то Access будет ругаться. Поэтому так не катит:
Код: plaintext
SELECT CurrentDB.Openrecordset("SELECT Name FROM MSysobjects").Fields("Name")

Что делать в таких случаях?
Оказывается можно использовать EVAL.
Вот примерчик:
Код: plaintext
SELECT EVAL("CurrentDB.Openrecordset(""SELECT Name FROM MSysobjects"").Fields(""Name"")")

Что это даёт нам? Внутри запроса можно динамически создавать запрос. Да и не только это!
Конечно можно внутри запроса использовать VBA функцию, которая динамически сформирует SQL текст запроса. Но я заинтересовался именно этим способом из-за mde / accde формата, где рядовой пользователь сам также сможет смастерить динамический запрос. Иногда это бывает полезным.
Конечно можно использовать так сказать статистические функции (DSum, DCount и т.д.). Но этот способ всё-таки более мощнее, ибо даёт возможность обратиться к разным источникам данных в зависимости от параметра. Чтобы было более понятнее покажу простой пример:
Код: plaintext
1.
2.
3.
4.
5.
SELECT
    ID,
    EVAL("CurrentProject.Connection.Execute(""" &
        IIf(Id< 100 , "SELECT Field1 AS X FROM Table1", "SELECT Field2 AS X FROM Table2") &
            """).Fields(""Name""")") AS SomeValue
FROM Table3
Как Вы видите из примера, если Id<100, то EVAL обращается к таблице "Table1", иначе к "Table2". А вот в статистических функциях (DSum, DCount и т.д.) как это делать не знаю. Может быть там также можно как-то изощряться, по крайнем мере мне не известен способ.


P.S. Всё что здесь я написал, смог обнаружить чисто экспериментально, а не по книжкам. Если у кого-то есть ссылка на соответствующую литературу или какие-то замечания, please, напишите. Буду очень признателен!
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37190558
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ошибся по поводу статистических функций. :)
Там тоже в динамике можно оказывается обращаться к разным источникам. В смысле текст подменять.
Сорю однако! :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37195556
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забавная функция Eval !!! Оказывается с её помощью даже в обычных запросах на выборку можно вносить изменения в объектах БД. Т.е. совершать следующие операции:
- удалить таблицу / запрос (DROP);
- удалить данные из таблицы / запроса (DELETE);
- добавить новые записи (INSERT)
- изменить записи (UPDATE).

И этим возможности функции не исчерпаны!!!

Допустим у нас есть таблица "Table1", где имеются поля "Num" (числовое), "Text" (Текстовое).
Вот примерчик для запроса на выборку данных:
Код: plaintext
1.
2.
3.
SELECT * FROM MSysObjects
WHERE
    IIf(IsNull(Eval("CurrentDB.Execute(""INSERT INTO Table1 VALUES(1, 'Test')"")"))=False, True,
    IsNull(Eval("CurrentDB.Execute(""UPDATE Table1 SET Num = Num + 10"")")))

" CurrentDB.Execute " внутри Eval всегда возвращает Null или ошибку. Здесь Eval внутри IIf нужен не для фильтра, а для запуска запроса на добавление. Т.к. условие IIf не выполняется, то запускается следующий блок (ложь), где уже запускается запрос на обновление.
Eval можно вписать почти где угодно внутри текста запроса (после SELECT / WHERE / GROUP BY / Order By), .
В принципе как я уже написал, можно даже удалить таблицу или запрос. Но так как "DROP TABLE" и "DROP PROCEDURE" нельзя использовать в обычных запросах, внутри Eval не следует использовать "CurrentDB.Execute". В таких случаях следует использовать "CurrentProject.Connection.Execute". Правда чтобы избежать сообщение об ошибке придётся чуть-чуть изощряться.
Вот примерчик:
Допустим у нас есть запрос "Запрос1", которого следует удалить. Сначала следует проверить существование запроса, если существует, то только тогда удалить.
Код: plaintext
1.
2.
SELECT IIf(DCount("Name", "MSysobjects", "Name='Запрос1'")> 0 ,
   IsNull(EVal("CurrentProject.Connection.Execute('DROP PROCEDURE Запрос1').ActiveConnection"))=False,
   False) AS Deleted;

Здесь "ActiveConnection" в принципе не столь важен, он необходим для того чтобы избежать сообщение об ошибке. Если запрос не существует, то не следует запускать Eval в данном случае. Именно поэтому потребовался IIF.
Примерно таким же образом можно запускать Execute на создание таблицы или запроса.

Можно с помощью Eval даже запустить программу находясь внутри запроса! Например так:
Код: plaintext
1.
2.
SELECT
Eval("Shell(""""""C:\Program Files\Microsoft Office\OFFICE11\MSACCESS.EXE""""
""""C:\Test.mdb"""""")");

Есть ещё 1 особенность: если мы используем Eval или даже пользовательской VBA функции, предназначенной для открытия объекта БД (Docmd.OpenTable, Docmd.OpenQuery, Docmd.OpenForm и т.д.), то Access будет ругаться и никак не будет открывать объект.


P.S.
Всё что я здесь написал про Eval можно было бы реализовать с помощью пользовательской VBA функции, что конечно же более естественно и разумно! Но я здесь просто попытался показать некоторые возможности Eval и что теоретически одним запросом можно совершать много операций словно хранимая процедура MS SQL Server.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37195615
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenЗабавная функция Eval !!! Оказывается с её помощью даже в обычных запросах на выборку можно вносить изменения в объектах БД. Т.е. совершать следующие операции:
- удалить таблицу / запрос (DROP);
- удалить данные из таблицы / запроса (DELETE);
- добавить новые записи (INSERT)
- изменить записи (UPDATE).

И этим возможности функции не исчерпаны!!!

...................
Такое использование функции Eval напоминает мину-ловушку. Невинный с виду предмет оказывается убийственным. Просто селект, вызывающий изменение объектов - идея того же порядка, ИМХО.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37219713
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindХотел написать своё наблюдение. Когда открываете редактор VBA, вы автоматически попадаете в последний из добавленных модулей (или модулей форм). Всегда один и тот же, если не добавляли новых. Это к топику: Сохранение позиции в модуле .

Случайно сегодня обнаружил такую закономерность. Допустим, мы хотим любой произвольный модуль (в том числе и модуль формы) отметить как модуль, автоматически загружаемый при первом же открытии VBA редактора.
Что для этого надо делать? CoolMind предложил свой вариант, который работает. Но оказывается есть и другой способ.
Открываем нужный модуль, специально вводим какой-нибудь ошибочный код во времени исполнения, из-за которого нельзя откомпилировать проект. Скажем такой код:
Код: plaintext
With CurrentDB.QueryDefs("")
Здесь я использовал "With", но не использовал "End With". Конечно это и есть типичная ошибка "Runtime error". Теперь проект нельзя компилировать, Access будет ругаться. Закрываем файл и сохраняем. Затем открываем файл и заходим в VBA редактор. Теперь будем всегда попадать первым в "отмеченный" модуль. Т.к. теперь ошибочный код нам больше не нужен, то его следует убрать. После этого не плохо бы и откомпилировать файл.

Вот так вот.

P.S. Обнаружено эмпирически, случайно. :-)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37228352
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я вот здесь нашёл простую функцию, которая преобразует байтовое число в бинарное выражение. Сам код выглядит так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Public Function sBin(ByVal b As Byte) As String
    Dim i As Integer
    
    For i =  0  To  7 
        If b And  2  ^ i Then
            sBin =  1  & sBin
        Else
            sBin =  0  & sBin
        End If
    Next i
End Function

Вроде простая функция. Проверил, работает. Но меня сначала удивила вот эта часть кода:
b And 2 ^ i
Для меня было не понятно, как это вообще работает.
Ведь если b не равно 0, значит он как бы True, ну и 2 ^ i всегда не 0. Значит если b не 0, то выражение должно вернуть True. Действительно попробовал вот такой запрос, который возвращает всегда True:
Код: plaintext
SELECT  3  And  7 
Попробовал и в VBA, но здесь результат в корне другой
Код: plaintext
1.
? 3  And  7 
 3 
Честно скажу, что поначалу не понял в чём тут дело. Открыл справочник и нашёл причину.
helpThe And operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in result ...
Давным-давно не открыл справочник про AND, вот и забыл, что And ещё и совершает побитовое сравнение.
Я не нашёл аналогичную функцию или оператор в Jet SQL для побитового сравнения. Если кто-нибудь подскажет, буду признателен.
А вот в MS SQL Server аналогичную функцию можно написать так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
CREATE FUNCTION fBin (@Value Tinyint) RETURNS Char( 8 )
AS
BEGIN
	DECLARE @I Tinyint, @V Char( 8 );

	/*	По умолчанию все переменные пустые (Null), поэтому им нужно присвоить
		первоначальные значения.
	*/
	SELECT @I =  0 , @V = '';

	WHILE @I <  8 
	BEGIN
		SELECT @V = CASE WHEN (@Value & POWER( 2 , @I)) >  0  THEN '1' ELSE '0' END + @V;
		SET @I = @I +  1 ;
	END

	RETURN @V;
END
Здесь побитовое сравнение совершает &.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37228386
ё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ё
Гость
studierenДействительно попробовал вот такой запрос, который возвращает всегда True:
Код: plaintext
SELECT  3  And  7 
Попробовал и в VBA, но здесь результат в корне другой
Код: plaintext
1.
? 3  And  7 
 3 

если в свойствах БД установить "синтаксис для СКЛ Сервер"
то такой же результат (как в VBA), можно получить в запросе
Код: plaintext
1.
SELECT  3  band  7  as a,  3  band  8  as b
ab30
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37228406
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемый Ё! Вы как всегда на высоте. Спасибочки ОГРОМНОЕ за науку!!!
Попробовал так, как Вы посоветовали (правда, слегка по другому):
Код: plaintext
1.
?CurrentProject.Connection.Execute("SELECT 3 Band 7 as A").Fields("A").Value
  3  

Не знал, что есть "BAND" (а не просто "AND"). Мой справочник молчит как партизан про этот оператор. А где можно почитать о нём?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37228424
ё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ё
Гость
studieren...
Не знал, что есть "BAND" (а не просто "AND"). Мой справочник молчит как партизан про этот оператор. А где можно почитать о нём?

...чесно говоря - я тоже про него (BAND) - узнал только здесь на форуме,
а в литературе - нигде не сталкивался... )))

там их несколько подобных
Код: plaintext
SELECT  3  band  7  AS a1,  3  band  8  AS b1,  3  bor  7  AS a2,  3  bor  8  AS b2,  3  bxor  7  AS a3,  3  bxor  8  AS b3
a1b1a2b2a3b330711411
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37228765
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно "бинарные" числа бывают иногда полезными, чтобы спрятать секретные свойства БД. Ну скажем так:
Можно создать таблицу, где будут хранится значения секретных свойств. Саму таблицу можно назвать как "~TMPCLP..." (вместо точек какое-нибудь слово или символы), чтобы таблицу невозможно было бы увидеть "штатными" инструментами Access. В этой таблице ключевое поле будет "ID", где будут числа 2^n (т.е. 1, 2, 4, 8, и т.д.), ну и дополнительные поля, где будут "секретные" свойства различных объектов (всё что угодно, да хоть дата истечения срока эксплуатации БД для определённой группы пользователей или серийные номера жёстких дисков пользователей, у кого есть право пользоваться программой и т.п.).
Далее, ещё одна таблица для настроек, где и будет поле с неким числом для настройки, скажем, пользовательского интерфейса. К примеру, если там число 7 (т.е. 1+2+4), то первые три записи из секретной таблицы будут относится к таблице "Настройка". Напрямую связать эти 2 таблицы обычном запросом при отключённом SQL ANSI 92 будет невозможно, поэтому не все продвинутые пользователи поймут что к чему. Можно внутри VBA с помощью "CurrentProject.Connection.Execute" запустить запрос и узнать какие свойства доступны для данного кода настройки.
Что-то вроде этого запроса:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Dim strSQL As String

strSQL = "SELECT N.*, T.*" & vbCrLf & _
"FROM Настройка AS N, [~TMPCLP_Table] AS T" & vbCrLf & _
"WHERE (N.ID Band T.ID) > 0"
With CurrentProject.Connection.Execute(strSQL)
    Do Until EOF
        ' Здесь получаем значения свойств и настраиваем БД.
        ' К примеру, устанавливаем запрет открытия какой-либо формы или отчёта
        ' определённым группам пользователей
        .MoveNext
    Loop
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37241671
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сегодня обнаружил такую закономерность:
Допустим, у нас есть таблица в какой-либо СУБД (скажем в MS SQL Server), где есть необязательное логическое поле (некое поле X bit Null). Ещё одна важная деталь: поле "X" не имеет значение по умолчанию! Пусть даже в данной таблице есть уникальный ключ (можно даже счётчик или можно даже timestamp).
Теперь в Accessе (в mdb | accdb файле) линкуем таблицу через ODBC.
Для эксперимента введём одну запись и сохраним, но при этом не трогаем поле "X" и тем самым в данном поле сохраним значение Null. Вот теперь данную запись невозможно не удалить, не вносить изменения, Access постоянно будет ругаться (см. картинку).

Есть мнение:
Видимо Access перед тем, как изменить или удалить данные сверяет «старые» данные и при такой сверки допускает значения только «True» и «False» для логических полей. Видать «кудесники» из Microsoftа забыли, что необязательные логические поля могут иметь значение «Null». Скорее всего, при сверке «старых» данных с «новыми» Access пользуется каким-то внутренним запросом, где фильтрует данные и получает пустой набор записей, когда логическое поле Null. Вот и Access «предполагает», что раз невозможно «достать» и сверять «старые» и «новые» записи, то кто-то уже заблокировал / изменил запись.

Как лечить?
Не пользуйтесь НЕ обязательными логическими полями или хотя бы обеспечьте всегда значение по умолчанию. А ещё лучше вместо логического поля использовать байтовое целое число (tinyint / byte).

P.S.
Вот ещё 1 топик, где показаны очень интересные случаи.
FAQ: Проблемы при работе с ADP/ADE
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37246558
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оказывается у Message box есть одна особенность:
когда выходит сообщение (не важно мы сами в программе вызвали или же программа сама сообщает о чём-то, например об ошибке), то можно нажать на Ctrl+C или Shift+Insert и тем самым скопировать в буфер обмена текст самого сообщения. Я раньше всегда "фотографировал" и вставлял в этом форуме рисунок Message Boxа. И какого было моё изумление, когда случайно обнаружил, что Ctrl+C работает. На всякий случай пролистал "официальный" help от Microsoftа, но там по этому поводу ничего не нашёл. Может как всегда "надёжно спрятали" где-то в недрах хелпа или может забыли.

P.S. Если баян, то уж извиняйте. Думаю для многих новичков всё-таки это новость. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37246601
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Когда-то (я уже не помню в каком топике) Анатолий из Киева предложил очень интересную функцию Message Boxа, где после истечения n секунд если пользователь не нажмёт на кнопку, то сообщение само закрывается. Вот собственно сама функция:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Function MsgBoxExt(Prompt As String, Optional Buttons As VbMsgBoxStyle = vbOKOnly, _
        Optional Title, Optional ByVal SecondsToWait As Integer) As Integer
    ' Аналог MsgBox с возможностью самовыключения.
    ' Возвращает код нажатой клавиши или -1, если время ожидания исчерпано.
    Dim wshShell As Object
    
    Set wshShell = VBA.CreateObject("WScript.Shell")
    MsgBoxExt = wshShell.PopUp(Prompt, SecondsToWait, Title, Buttons)
End Function

Здесь вместо стандартного для VBA функции MsgBox использован объект "WScript.Shell" и его метод "PopUp". Оказывается и у этого способа можно скопировать текст самого сообщения в буфер обмена, когда выходит сообщение.
А вот когда аварийно останавливается программа и выходит не совсем "красивое" сообщение, то увы, я не смог скопировать в буфер обмена. Пришлось "фотографировать" (см. картинку).

P.S. А какие сообщения можно таким образом скопировать в буфер обмена, а какие нет никто не подскажет? Был бы признателен.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37249564
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не большое уточнение. Вот эти слова, отмеченные красным цветом, всё-таки оказались лишними, я тут немного ошибся:
studieren...(не важно мы сами в программе вызвали или же программа сама сообщает о чём-то, например об ошибке)...
Если мы перехватываем ошибку и сами "красиво" сообщаем пользователю в MsgBox, то можно копировать текст сообщения. Ну а если программа сама сообщает об ошибке (к примеру запускаем запрос с ошибкой), то сообщение в лучшем случае можно "фотографировать", а копировать нельзя.
Увы, Inputbox, пользовательская диалоговая форма и многое другое - "не копируемые".
Я всё больше думаю, что только пользовательский MsgBox имеет такую особенность.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37251424
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я когда-то написал вот здесь как можно в запросах в режиме конструктора создавать алиасы (псевдонимы) таблиц не заходя в режим SQL. В справочнике MS Access 2003 есть такая статья "Создание псевдонимов таблиц в запросе (ADP)", где собственно и написано о псевдонимах.
Примечание. Сведения в данном разделе относятся только к проектам Microsoft Access (.adp).

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

Необходимо создать инструкцию в области SQL, которая будет более короткой и простой для чтения.
При частом обращении в запросе к имени таблицы, представления или функции, например к полным именам столбцов, необходимо быть уверенным, что не превышен предел количества знаков в запросе.
При работе с несколькими копиями одной и той же таблицы, представления или функции (например в самообъединении) необходимо указать ссылку на одну из копий.
Например, можно создать псевдоним "e" для таблицы employee_information, а затем использовать "e" при ссылке на нее.

В окне базы данных в списке Объекты нажмите кнопку Запросы , выберите запрос, который нужно открыть, и на панели инструментов окна базы данных нажмите кнопку Конструктор.
В области схемы щелкните правой кнопкой таблицу, представление или функцию, для которой необходимо создать псевдоним, и выберите в контекстном меню команду Свойства.
В диалоговом окне Свойства введите псевдоним в поле Псевдоним.
При создании псевдонима таблицы конструктор запросов подставит псевдоним вместо соответствующего имени таблицы в столбце «Таблица» в области сетки.

Примечание. Если для таблицы создан псевдоним, то при ссылке на таблицу в инструкции SQL необходимо использовать именно псевдоним (использовать оригинальное имя таблицы нельзя).

В справочнике написано, что данный способ относится только к проектам adp. Но на самом деле и в обычных mdb файлах подобным образом также возможно создавать псевдонимы. (См. рисунок)
Там в свойствах помимо "Псевдоним" есть ещё другое не менее интересное свойство "Источник", где можно указать путь любой другой базы и тогда Access будет тянуть информацию из указанной базы. Например, напишем так: "C:\Test.mdb", после этого смотрим в режиме SQL текст запроса.
Код: plaintext
SELECT * FROM [C:\Test.mdb].MSysObjects AS O
В справочниках Accessа я не встретил ни одного умопинания о том, как надо написать в данное свойство текст подключения, чтобы достать таблицу или представление из другой СУБД, например из MS SQL Server. Оказывается всё очень просто. Нужно написать так (это пожалуй самый простой текст подключения):
Код: plaintext
ODBC;DSN=НазваниеDSN;Database=НазваниеБД;
Можно также указывать логин и пароль здесь же:
Код: plaintext
ODBC;DSN=НазваниеDSN;Database=НазваниеБД;UID=SA;PWD= 123456 
Таким образом можно достать только таблицу или представление из другой СУБД, а вот другие объекты БД (функция, хранимая процедура и т.д.) нельзя. Запрос в таких случаях работает так, как если бы он был линкованной таблицей и станет обновляемым, если конечно же имеется первичный ключ / уникальный индекс.
Текст запроса в режиме SQL выглядит примерно так:
Код: plaintext
SELECT * FROM [ODBC;DSN=НазваниеDSN;Database=НазваниеБД;UID=SA;PWD= 123456 ].dbo.Table1 AS T
Здесь название владельца / схемы "dbo" можно пропустить.
Есть ещё одна альтернатива: предложение IN, с помощью которого также возможно достать таблицы или представления из MS SQL Server (предполагаю, что и с другими видами СУБД дела обстоят аналогичным образом). Но тут есть небольшие сюрпризы, о которых нигде не пишут (во всяком случае я не нашёл).
Сначала цитата из справочника:
Предложение IN
Определяет таблицы в любой внешней базе данных, с которой ядро базы данных Microsoft Jet может установить связь, например в базе данных dBASE, Paradox или внешней базе данных с ядром Microsoft® Jet.

Синтаксис
Чтобы определить результирующую таблицу:

[SELECT | INSERT] INTO назначение IN
{путь | ["путь" "тип"] | ["" [тип; DATABASE = путь]]}

Чтобы определить исходную таблицу:

FROM выражение IN
{путь | ["путь" "тип"] | ["" [тип; DATABASE = путь]]}

Ниже перечислены аргументы инструкции SELECT, содержащей предложение IN:

Элемент Описание
назначение Имя внешней таблицы, в которую добавляются данные.
выражение Имена одной или нескольких таблиц, из которых отбираются данные. Это выражение может быть именем отдельной таблицы, именем сохраненного запроса или результатом операции INNER JOIN, LEFT JOIN или RIGHT JOIN.
путь Полный путь к каталогу или файлу, в котором находится таблица.
тип Имя типа базы данных, в которой создана таблица, если база данных несовместима со стандартом Microsoft Jet (например, dBASE III, dBASE IV, Paradox 3.x или Paradox 4.x).


Дополнительные сведения
С помощью предложения IN можно одновременно подключиться только к одной внешней базе данных.

В некоторых случаях аргумент путь задает ссылку на каталог, содержащий файлы базы данных. Например, во время работы с таблицами баз данных dBASE, Microsoft FoxPro® или Paradox аргумент путь задает ссылку на каталог, содержащий файлы .dbf или .db. Имя файла таблицы извлекается из аргументов назначение или выражение.

Чтобы определить базу данных, несовместимую со стандартом Microsoft Jet, следует добавить к ее имени знак точки с запятой (;) и заключить имя в одинарные (' ') или прямые (" ") кавычки. Например, 'dBASE IV;' или "dBASE IV;".

Кроме того, для описания внешней базы данных можно использовать зарезервированное слово DATABASE. Например, следующие строки описывают одну и ту же таблицу:

... FROM Таблица IN "" [dBASE IV; DATABASE=C:\DBASE\DATA\SALES;];

... FROM Таблица IN "C:\DBASE\DATA\SALES" "dBASE IV;"

Там же есть примеры подключения (но только почему-то о MS SQL Server ни слова!):
Предложение IN, примеры

В следующей таблице демонстрируется использование предложения IN для отбора данных из внешней базы данных. В примерах предполагается, что таблица «Клиенты» сохраняется во внешней базе данных.

База данных Инструкция SQL База данных Microsoft® Jet SELECT КодКлиента FROM Клиенты IN Заказы.mdb WHERE КодКлиента Like "A*"; dBASE III или IV. Для отбора данных из таблицы dBASE III, замените "dBASE III;" на "dBASE IV;". SELECT КодКлиента FROM Клиенты IN "C:\DBASE\DATA\SALES" "dBASE IV;" WHERE КодКлиента Like "A*"; dBASE III или IV в синтаксисе Database. SELECT КодКлиента FROM Клиенты IN "" [dBASE IV; Database=C:\DBASE\DATA\SALES;] WHERE КодКлиента Like "A*"; Paradox 3.x или 4.x. Для отбора данных из таблицы Paradox версии 3.x, замените "Paradox 3.x;" на "Paradox 4.x;". SELECT КодКлиента FROM Клиенты IN "C:\PARADOX\DATA\SALES" "Paradox 4.x;" WHERE КодКлиента Like "A*"; Paradox 3.x или 4.x в синтаксисе Database. SELECT КодКлиента FROM Клиенты IN "" [Paradox 4.x;Database=C:\PARADOX\DATA\SALES;] WHERE КодКлиента Like "A*"; Книга Microsoft Excel SELECT КодКлиента, Название FROM [Клиенты$] IN "c:\documents\xldata.xls" "EXCEL 5.0;" WHERE КодКлиента Like "A*" ORDER BY КодКлиента; Именованный диапазон электронной таблицы SELECT КодКлиента, Название FROM ДиапазонКлиенты IN "c:\documents\xldata.xls" "EXCEL 5.0;" WHERE КодКлиента Like "A*" ORDER BY КодКлиента;

Как же следует указать текст подключения в предложениях IN, чтобы получить данные из определённой таблицы или представления?
Сначала укажем пустую строку (либо 2 апострофа '', либо 2 кавычки "", либо 2 квадратные скобки []) или же любое слово, но без пробелов и только потом текст подключения. Текст подключения также следует написать либо внутри апострофов, либо кавычек, либо квадратных скобок. Вот варианты
Код: plaintext
SELECT * FROM Table1 IN ЛюбоеСловоНоТолькоБезПробеловИЖелательноБезПлохихСимволов 'ODBC;DSN=НазваниеDSN;Database=НазваниеБД;UID=SA;PWD=123456'
Код: plaintext
SELECT * FROM Table1 IN "" [ODBC;DSN=НазваниеDSN;Database=НазваниеБД;UID=SA;PWD= 123456 ]
Как вы видите кавычки, апострофы, квадратные скобки можно использовать вперемежку.
Но в то же время также можно текст подключения разделить на 2 части и указать отдельно. Типа так:
Код: plaintext
SELECT * FROM Table1 IN 'Database=НазваниеБД' [ODBC;DSN=НазваниеDSN;UID=SA;PWD= 123456 ]
При этом если указан логин и пароль, то следует их указать во 2-части текста подключения.
Если логин и пароль пользователя не указан, а также отсутствует параметр " Trusted_Connection=Yes ", то при первом запуске запроса выходит диалоговое окно, куда и следует ввести логин и пароль для доступа к серверу.

P.S. Может кто-нибудь подскажет ссылку на "официальную" литературу, где можно прочесть о всех нюансах предложения IN? А может кто-то уже досконально изучил данный предмет и знает многие-многие нюансы / особенности / "секреты"? Не поделитесь?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37254943
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren
Код: plaintext
With CurrentDB.QueryDefs("")

Большое спасибо за проведённое исследование.
Я в Access'е уже редко, пробовал в Word (в VBA), не получилось. Ставлю любую типичную ошибку, например, fgd = 0, при попытке компиляции выдаёт ошибку, сохраняю, выхожу, захожу снова - натыкаюсь на не нужный мне модуль. В 2007 версии Word, по-моему, эта особенность исправлена, и там можно попадать сразу в последний исправленный модуль.
Наверное, это годится для Access.
Впрочем, всё по той же ссылке YBW, а затем и я, обнаружили, что способ Serge Gavrilov работает, а он, видимо, взял откуда-то с другого сайта, судя по комментариям в этом Add-In'е.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37255058
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindВпрочем, всё по той же ссылке YBW, а затем и я, обнаружили, что способ Serge Gavrilov работает, а он, видимо, взял откуда-то с другого сайта, судя по комментариям в этом Add-In'е.
Что я взял с другого сайта? Комментарии в каком Add-In?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37255153
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serge Gavrilov, Сохранение позиции в модуле
Забыл дописать, что нужно написать 2 bat-файла:
install.bat:
Код: plaintext
@regsvr32 bin\CodePositionRestore.dll -s
uninstall.bat:
Код: plaintext
@regsvr32 bin\CodePositionRestore.dll -u -s
и положить их в папку SavePos, запускать по желанию.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37255304
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindSerge Gavrilov, Сохранение позиции в модуле
там вообще нет комментариев
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37255374
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindstudieren
Код: plaintext
With CurrentDB.QueryDefs("")

Большое спасибо за проведённое исследование.
Я в Access'е уже редко, пробовал в Word (в VBA), не получилось. Ставлю любую типичную ошибку, например, fgd = 0, при попытке компиляции выдаёт ошибку, сохраняю, выхожу, захожу снова - натыкаюсь на не нужный мне модуль. В 2007 версии Word, по-моему, эта особенность исправлена, и там можно попадать сразу в последний исправленный модуль.
Наверное, это годится для Access.
Впрочем, всё по той же ссылке YBW, а затем и я, обнаружили, что способ Serge Gavrilov работает, а он, видимо, взял откуда-то с другого сайта, судя по комментариям в этом Add-In'е.

День добрый, CoolMind!
Сначала не понял о чём речь, а потом вспомнил. Да, действительно я написал особенность А2003. После Вашего сообщения попробовал в Excel 2003, там тоже такой "трюк" не проходит, в смысле не попадаем в "ошибочный" модуль. Значит это касается только А2003.
А вообще я так и не понял, почему и по какому принципу некоторые модули внутри A2003 открыты, когда мы первый раз запускаем, а некоторые закрыты.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37255389
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serge Gavrilovтам вообще нет комментариев
Connect.Dsr:
Код: 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.
   Description     =   "Save and restore  cursor position in VBA Code"
   DisplayName     =   "Save and restore cursor position in VBA Code"
   AppName         =   "Visual Basic for Applications IDE"

.................

Public VBEInstance           As VBIDE.VBE
Private mfrmWatcher          As VB.Form
'------------------------------------------------------
'this method adds the Add-In to VB
'------------------------------------------------------
Private Sub AddinInstance_OnConnection(ByVal Application As Object, ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, ByVal AddInInst As Object, custom() As Variant)
    On Error GoTo error_handler
    
    'save the vbe instance
    Set VBEInstance = Application
    Set mfrmWatcher = New frmWatcher
    
    Set mfrmWatcher.VBEInstance = Me.VBEInstance
    mfrmWatcher.Timer1.Interval =  100 
    
    Exit Sub
    
error_handler:
    
    MsgBox Err.Description
    
End Sub

'------------------------------------------------------
'this method removes the Add-In from VB
'------------------------------------------------------
Private Sub AddinInstance_OnDisconnection(ByVal RemoveMode As AddInDesignerObjects.ext_DisconnectMode, custom() As Variant)
    Unload mfrmWatcher
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37255524
Lockpickup
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вот еще интересный "факт"...

1. Снял флаг отображения с таблицами и проч.
Файл->Параметры->Текущая база данных->снять галку Область перехода->Перегрузить БД
2. Убрал встроенные меню MSAccess (Property базы "AllowFullMenus").
3. Вижу результат как на прикрепленном файле (все в порядке, все закрыто).
4. См. след пост т.к. не знаю как 2 картинки прикрепить...
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37255534
Lockpickup
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Теперь правым кликом на кнопочку "микрософт", выбираем пункт "Настройка панели быстрого доступа" и вуаля.
Спрашивается, за что боролся?
Может кто знает, как закрыть этоти "лаз" от пользователей?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37256037
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindSerge Gavrilovтам вообще нет комментариев
Connect.Dsr:
Код: plaintext
1.
2.
3.
4.
5.
6.
'------------------------------------------------------
'this method adds the Add-In to VB
'------------------------------------------------------
'------------------------------------------------------
'this method removes the Add-In from VB
'------------------------------------------------------
Я имел в виду мои комментарии.
А как эти комментарии, которые вы приводите, указывают, что что-то взято с какого-то сайта?
Если бы вы когда-либо писали Addin-ы на VB6, то знали бы, что эти комментарии появляются "автоматом" при создании нового проекта, если шаблоном был выбран Addin. Попробуйте.

Если я добавляю комментарии, то в основном пишу их тоже на английском.
Если использую чей-то код, то стараюсь приводить в комментариях источник, откуда он взят.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37256218
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lockpickup,

Я просто переименовал формат файла "accdb" на "accdr", т.е. сделал как бы "Runtime" и у меня получился "не активный" меню (см. картинку).
Не вариант?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37256236
Фотография CoolMind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serge Gavrilov, действительно, с этим трудно спорить, поэтому я и написал слово "видимо". Извините, пожалуйста. Очень рад, что это Ваш код, и он очень помогает в работе.

Добрый день, studieren! Ваш метод тоже очень удобен для случая Access, потому что при установке Add-In во всех Офисных приложениях по окончании работы будет задаваться вопрос о сохранении. Для Access это и так общепринято, а вот для Word было бы не очень удобно, поэтому я обычно запускаю install.bat перед сохранением позиции, а по окончании - uninstall.bat. Требуется редко, но метко.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37256302
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CoolMindSerge Gavrilov, действительно, с этим трудно спорить, поэтому я и написал слово "видимо". Извините, пожалуйста. Очень рад, что это Ваш код, и он очень помогает в работе.
Хорошо, а код был приведен в качестве примера возможного решения...
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37256397
Lockpickup
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren, очень даже вариант!! Благодарствую.

Только я переименовал .accde в .accdr.
И, что очень приятно, там нет панельки "Область навигации".
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37259420
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы узнать как долго работает Windows можно воспользоваться вот таким кодом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Private Declare Function GetTickCount Lib "kernel32" () As Long

Sub HowLongWindowsWork()
    Dim lngTotal As Long
    Dim intHour As Integer, intMinute As Integer, intSecond As Integer
    
    lngTotal = Format(GetTickCount() /  1000 , "0") 'всего секунд
    intHour = Int(lngTotal /  3600 )
    lngTotal = lngTotal - CLng(intHour) *  3600 
    intMinute = Int(lngTotal /  60 )
    intSecond = lngTotal - CLng(intMinute) *  60 

    MsgBox "Ваш компьютер работает в эту загрузку " & Str(intHour) & " час. " & _
        Str(intMinute) & " мин. " & Str(intSecond) & " сек.", vbInformation
End Sub

Код взял отсюда и слегка переделал.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37268385
Guest33
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Application.ADOConnectString - Что это? В хелпе нет, в объект бровсере нет, в подсказке (после точки) не возникает. На форуме - один пост ( 7301856 ). Зачем он?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Sub test_application_adoconnectstring()
Dim r As New ADODB.Recordset

r.Open "select count(*) from marks", _
       Application.ADOConnectString & ";User ID=Admin; Password=", _
       adOpenStatic, _
       adLockReadOnly
Debug.Print r( 0 )
r.Close: Set r = Nothing
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37268474
Фотография Serge Gavrilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Guest33...в объект бровсере нет, в подсказке (после точки) не возникает...
Есть, включите в Object Browser "Show Hidden Memberы"
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37276569
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересный факт:
Если во внутреннем запросе использовать какую-нибудь VBA функцию, но при этом во внешнем запросе не ссылаться на данное поле (столбец) в фильтрах и в сортировках, иначе говоря если бестолково использовать VBA функцию во внутреннем запросе, то Access полностью ИГНОРИРУЕТ данную функцию, словно её там нет.
Чтобы было более понятно приведу такой пример.
Создаю такую функцию
Код: plaintext
1.
2.
Function Test(str As String)
   MsgBox str
End Function
А теперь запускаю вот такой запрос
Код: plaintext
1.
2.
Select Name From
(SELECT Name, Test(Name) AS X
FROM MSysObjects) AS O;
Access ни разу не будет давать MsgBox!!!
А вот при таком запросе замучает MsgBoxами!
Код: plaintext
1.
2.
3.
Select Name From
(SELECT Name, Test(Name) AS X
FROM MSysObjects) AS O
Order By X;
Вообщем-то это логично и даже совсем не плохо. Access экономит ресурсы там, где это возможно. Я предполагаю, что со звёздочками "*" дела обстоят аналогично, т.е. даже если во внутренним запросе используем звёздочку "*", то скорее всего Access будет "обращать внимание" только на нужные поля, а остальных будет игнорировать.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37276605
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ещё одна деталь:
Данное утверждение оказывается верно и для запросов внутри запроса. Т.е. если мы используем какой-нибудь запрос (скажем "Запрос1") как источник данных для другого запроса и при этом в первом запросе использованы VBA функции, которых мы не используем во втором запросе, то и в таких случаях Access игнорирует VBA функцию.
Сохраним такой запрос под именем "Запрос1":
Код: plaintext
1.
SELECT Name, Test(Name) AS X
FROM MSysObjects
Теперь запускаем другой запрос
Код: plaintext
1.
SELECT Name
FROM Запрос1
Опять ни одного MsgBox! :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37277687
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

А тут и не должно быть его, ведь select name, а не test. И вообще с сохранёнными и несохранёнными запросами много фишек, одни только вычисляемые поля чего стоят.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37277779
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ли создать такой запрос с параметром, который возвращает список названий запросов, содержащих определенный фрагмент SQL текста?
Да, можно и на самом деле всё очень просто. Вот один из вариантов:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
PARAMETERS Fragment Text (  255  );
SELECT Qry.Query, Qry.SQL_Text
FROM [TABLE
    (SELECT O.Name AS Query, Eval("CurrentDB.Querydefs('" & O.Name & "').SQL") AS SQL_Text
    FROM MSysObjects AS O
    WHERE O.Type =  5 
    ORDER BY O.Name)]. AS Qry
WHERE IsNull(Fragment) OR SQL_Text Like ('*' & Fragment & '*');
Здесь если не укажем фрагмент SQL текста запроса, то получим весь список запросов.


А если у кого-то есть ещё более простое решение, please поделитесь. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37286253
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если в файле mdb имеются несколько таблиц, присоединённых через ODBC (linked table) к различным базам данных из разной СУБД, то при первом обращении к такой таблице появляется специальное диалоговое окно, куда пользователь должен ввести логин и пароль. Видимо Access где-то запоминает логин и пароль пользователя, т.к. при повторном обращении к одной и той же таблице уже не спрашивает аутентификацию. Ну а если открыть другую таблицу, присоединённой к другой СУБД, то вновь появится диалоговое окно для аутентификации.
Допустим, логин и пароль пользователя абсолютно одинаковый для всех БД из разных СУБД.
Как же сделать так, чтобы Access спрашивал логин и пароль пользователя только один раз?
Я как-то уже спрашивал этот вопрос вот здесь, где уважаемый Ё подсказал достаточно оригинальный способ решения проблемы.
Для этого в Accessе создаём рабочую группу, где следует создать идентификационные данные пользователя (логин и пароль) аналогичные с другими СУБД. Обязательно также следует запаролить пользователя "Admin" иначе при открытии файла Access не будет спрашивать пароль. Когда мы откроем и введём логин и пароль для Accessа, то этого будет достаточно, больше при обращении присоединённых таблиц аутентификация пользователя не требуется.
Всё вроде бы нормально работает. Но!!!
Начиная с А2007 теперь Microsoft отказывается от рабочей группы (файл mdw). Вообще-то у рабочей группы была ещё 1 полезная особенность: можно было защитить не только таблицы и запросы, но и такие объекты базы как формы и отчёты. Теперь, увы, они беззащитны. Но это уже другая тема.
Как же теперь поступить, если файл в формате А2007 или даже А2010?
Один из самых простых способов решения это «временные запросы к серверу».
Для этого сначала создаём форму, где требуется ввести логин и пароль пользователя. Для поля «пароль» ставим маску ввода «PASSWORD». Теперь создаём «временный» запрос таким образом:
Код: plaintext
Dim xQuery As DAO.QueryDef\nDim strSQL As String\nDim strCnn As String\nDim i As Byte, blnCheck As Boolean\n\n\' Сначала на всякий случай следует проверить введен ли логин пользователя\nIf IsNull(txbUser.Value)=True Then\n    MsgBox "Введите логин пользователя.", vbInformation\n    txbUser.Setfocus\n    Exit Sub\nEnd If\n\' Создаём временный запрос.\nSet xQuery = CurrentDB.CreateQueryDef("")\n\' Чтобы долго не ждать можно время ожидания сократить до 1 секунды.\n\' Как не странно, если пропустить этот код, то Access почему-то при первом\n\' запуске может зависать где-то на 15-20 секунд. Вроде бы запрос простейший,\n\' никаких сложных вычислений, но всё же!\nxQuery.ODBCTimeout =  1 \n\nstrSQL = "SELECT 1 AS Test;"\nOn Error Resume Next\n\' Для примера попробуем присоединиться к 3 БД.\nFor i =  1  To  3 \n    strCnn = "ODBC;DSN=" & Choose(i, _\n        "НазваниеDSN1;Database=НазваниеБД1;", _\n        "НазваниеDSN2;Database=НазваниеБД2;", _\n        "НазваниеDSN3;Database=НазваниеБД3;") & _\n        "UID=" & txbUser.Value & ";PWD=" & txbPassword.Value & ";"\n    xQuery.Connect = strCnn\n    xQuery.SQL = strSQL\n    blnCheck = xQuery.Openrecordset.Fields( 0 ).Value\n    If Err.Number <>  0  Then\n        MsgBox "Введены неверные идентификационные данные пользователя!", vbExclamation\n        Exit Sub\n    End If\nNext i\nxQuery.Close\nSet xQuery = Nothing

После всего этого можно без проблем открыть любую присоединённую таблицу и при этом не вводить идентифицирующие данные пользователя.

P.S. Прилагаю mdb файл (в формате A2003), где есть форма «Authentication». Там есть ещё одна дополнительная таблица «USys_DefaultUser», которая необходима для определения логина пользователя по умолчанию. Программа запоминает логин последнего пользователя в данной таблице и при следующем запуске Acccessа по умолчанию логин будет появляться. Разумеется, и с помощью API функций можно узнать последнего пользователя, но на мой взгляд данное решение более простое.
Можете импортировать форму «Authentication» и таблицу «USys_DefaultUser» в свою базу. Только не забудьте в модуле формы заменить «НазваниеDSN» и «НазваниеБД» на реальное значение, ну и саму форму можно повесить на стартап.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37318799
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прилагаю файл "FindObject.mdb" (в формате А2003), где есть форма "FindObject", с помощью которой можно:
- найти объект БД по фрагменту названия
- удалить объект БД (для этого нужно выбрать из списка название объекта и нажать на DELETE)
- получить некоторые свойства объекта (например названия полей таблицы / запроса)
- поиск запроса по фрагменту SQL текста запроса (3-закладка)
- выбрать объект в окне БД (кнопка "очки", можно нажать на Alt+7)
- открыть объект в режиме конструктора ("линейка", Alt + 8)
- открыть / запустить объект ("!", Alt + 9)

В реальных базах, где могут быть множества объектов, данная форма очень помогает быстро найти любой объект.
Также рекомендуется создать макрос "AUTOKEYS", где следует назначить на определенную клавишу вызов формы "FindObject", к примеру F4.
Т.к. данная форма опирается на системную таблицу MSysObjects, которая отсутствует в adp, она применима только в "mdb" и в "accdb" файлах (проверено в А2007, там тоже работает).
Когда мы вручную удаляем таблицу или запрос, Access на самом деле не удаляет, а переименовывает объект типа так "~TMPCLP456161". С помощью формы "FindObject" можно окончательно удалить объект из базы.


P.S. Может быть кому-то пригодиться.
Жду замечаний и критики от аудитории. Если найдёте косяк, please пишите.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37345257
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Слегка улучшил файл "FindObject.mdb" и исправил некоторые ошибки.
Теперь можно заменить программно фрагмент SQL текста запроса. Например, если Вы переименовали таблицу, то теперь программно можете переделать все запросы, которые в своём тексте ссылаются на переименованную таблицу.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37345281
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В хелпе как-то "мелко" написано по поводу таблицы "MSysConf".
Примечание. Сведения в данном разделе относятся только к базам данных Microsoft Access (.mdb).
Важно При создании таблицы «MSysConf» необходимо правильно выполнить ее настройку, иначе подключение к таблице базы данных SQL (База данных SQL. База данных, для управления которой используется язык SQL (Structured Query Language).) будет невозможно.
При администрировании базы данных SQL, в качестве клиентского интерфейса для работы с которой используется Microsoft Access, можно создать в базе данных SQL таблицу с именем «MSysConf», помогающую управлять взаимодействием этих двух приложений. Таблица «MSysConf» имеет две функции.
- Позволяет отключать средство, обеспечивающее пользователям возможность сохранять в клиентской базе данных Microsoft Access имя и пароль для подключения к связанной базе данных SQL.
- Оптимизирует способ заполнения Microsoft Access записей в фоновом режиме при простое, позволяя задать количество одновременно загружаемых строк данных и время задержки (в секундах) между загрузками. Если таблица «MSysConf» не создана, Microsoft Access использует стандартные значения: 100 записей с загрузкой через каждые 10 секунд.
Структура таблицы «MSysConf»

Таблица «MSysConf» базы данных SQL должна иметь следующую структуру.
Имя столбца Тип данных Пустое значение Config Тип данных, соответствующий 2-байтовому целому числу НетchValue VARCHAR(255) Да nValue Тип данных, соответствующий 4-байтовому целому числу Дапримечания VARCHAR(255) Да


Примечание. Если в используемом источнике данных учитывается регистр знаков, имена таблицы и столбцов должны вводиться точно так, как они написаны.

Данные в таблице «MSysConf»

В таблице «MSysConf» допустимы три записи. В следующей таблице перечислены значения, которые следует ввести в поля «Config» и «nValue». Остальные столбцы зарезервированы для дальнейшего использования, и их содержимое игнорируется.
Config nValue Результат 101 0 Запрет локального хранения сетевого имени и пароля связанной таблицы. 101 1 Разрешение локального хранения сетевого имени и пароля связанной таблицы. 102 D D — время задержки в секундах между операциями загрузки. 103 N N — число загружаемых строк.

Примечание. Более длительное время задержки снижает загруженность сети, но увеличивает время, в течение которого данные открыты только для чтения (если сервер использует блокировку, допускающую только чтение).
Создал на стороне SQL Server таблицу "MSysConf", но особой разницы не почувствовал. Ввёл значения 101, 0 в соответствующие поля "Config" и "nValue". Однако во всех линкованных таблицах и запросах к серверу, где заранее были сохранены логин и пароль пользователя не удалились. :)
Когда создаю новую линкованную таблицу с помощью мастера, то обычно Access спрашивал сохранить ли логин и пароль. После этого перестал спрашивать. И это Microsoft называет "Запрет локального хранения сетевого имени и пароля связанной таблицы" ?
Ну и "время задержки", а также "число загружаемых строк" также не совсем понятны. Я поэкспериментировал, но особой разницы не заметил. Кто нибудь может подробно объяснить об этой таблице? В каких случаях она может быть действительно полезной?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37345302
попробуй скачать файл отсюда или найди его на msdn или support.microsoft.com

http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=492885&msg=4900746
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37345551
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сосед-акцессник,

Спасибки Вам и "бабай". Интересный файл, там много чего интересного подробно написано.
Читаю и изучаю.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37348147
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как программно отправить на печать только определенные страницы отчета с заданным количеством экземпляров?

Допустим, имеется отчёт с несколькими страницами. Скажем - 100 страниц. Нам нужно напечатать все страницы начиная с 10 по 20 в 2-х экземплярах. Как это сделать программно?

Для этого создадим следующую VBA функцию:
Код: 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.
Function PrintReport(ReportName As String, _
        FirstPage As Integer, LastPage As Intiger, CopyQuantity As Byte)
    Dim blnIsLoaded As Boolean
    
    ' Следует проверить существование отчёта.
    ' Если произойдёт ошибка 2467, значит отчёт не существует.
    On Error Resume Next
    blnIsLoaded = CurrentProject.AllReports(ReportName).IsLoaded
    If Err.Number =  2467  Then
        MsgBox "Отчёт """ & ReportName & """ не существует в базе данных! " & _
            "Проверьте название отчёта.", vbInformation
        Exit Function
    ElseIf Err.Number <>  0  Then
        MsgBox Err.Description, vbInformation
        Exit Function
    End If
    
    ' Проверим числа
    If FirstPage <=  0  Or LastPage <=  0  Or CopyQuantity =  0  Then
        MsgBox "Введите положительное целое число в качестве начальной / последней " & _
            "страницы / количества эксземпляров отчёта.", vbInformation
        Exit Function
    ElseIf FirstPage > LastPage Then
        MsgBox "Номер начальной страницы не должен быть больше порядкового номера " & _
            "конечной страницы.", vbInformation
        Exit Function
    End If
    
    If blnIsLoaded = False Then
        DoCmd.OpenReport ReportName, acPreview, , , acHidden
    End If
    
    DoCmd.PrintOut acPages, FirstPage, LastPage, , CopyQuantity, False
    If blnIsLoaded = False Then
        DoCmd.Close acReport, ReportName
    End If
End Function

Код: plaintext
PrintReport "Отчёт",  10 ,  20 ,  2 
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37354519
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник

Очепятка в предыдущем посте. :)
Вместо "Intiger" читать как "Integer" в параметрах функции.

Как известно в VBA есть стандартный MsgBox.
В принципе и в библиотеке "WSript.Shell" есть свой MsgBox.
Код: plaintext
Function MsgBoxExt(Prompt As String, Optional Buttons As VbMsgBoxStyle = vbOKOnly, _\n        Optional Title, Optional ByVal SecondsToWait As Integer) As Integer\n    \' Аналог MsgBox с возможностью самовыключения.\n    \' Возвращает код нажатой клавиши или -1, если время ожидания исчерпано.\n    Dim wshShell As Object\n    \n    Set wshShell = VBA.CreateObject("WScript.Shell")\n    MsgBoxExt = wshShell.PopUp(Prompt, SecondsToWait, Title, Buttons)\nEnd Function

Есть также у Win API свой MsgBox.
Код: plaintext
Private Declare Function MessageBox _\n        Lib "user32.dll" Alias "MessageBoxA" ( _\n        ByVal hWnd As Long, _\n        ByVal lpText As String, _\n        ByVal lpCaption As String, _\n        ByVal wType As Long) As Long\n\nFunction WinAPI_MsgBox(Prompt As String, Title As String, WinType As Long) As Long\n    WinAPI_MsgBox = MessageBox( 0 &, Prompt, Title, WinType)\nEnd Function

MsgBox в WinAPI и в WSript.Shell в отличии от стандартного MsgBox в VBA не модальный, т.е. даже когда Вы получаете MsgBox и ещё не нажали на кнопку, то Вы можете параллельно запускать любую процедуру/функцию и VBA параллельно будет выполнять. Но только клавиша F11 при этом не работает. :)


P.S. Случайно наткнулся на топик MsgBox на нерусском в русской версии win и MA?, где уважаемый Бенедикт предложил способ вывода текста MsgBox на любом языке (хоть на арабском).
Код уважаемого Бенедикта
Код: plaintext
Private Declare Function MessageBoxW Lib "user32" ( _\n   ByVal hWnd As Long, ByVal lpText As String, _\n   ByVal lpCaption As String, ByVal wType As VbMsgBoxStyle) As VbMsgBoxResult\n\nSub Hello()\n MessageBoxW  0 , _\n             StrConv("!" & ChrW(&HFE8E) & ChrW(&HFE92) & ChrW(&HFEA3) & _\n                     ChrW(&HFEAE) & ChrW(&HFEE3), vbUnicode), _\n             StrConv("Мархаба!", vbUnicode), _\n             vbExclamation + vbMsgBoxRight + vbMsgBoxRtlReading\nEnd Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37363099
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы в запросах произвести условную сортировку, т.е. если выполняется 1-условие, то 1-блок данных сортируется первым, если 2-условие, то 2-блок и т.д., обычно пользуются функцией IIf. Что-то вроде этого:
Код: plaintext
1.
2.
SELECT Name
FROM MSysObjects AS O
ORDER BY IIf(Name='Tables',  1 , IIf(Name='Forms',  2 , IIf(Name='Reports',  3 ,  4 )))
Оказывается в MS Access этот же запрос можно запустить и без IIf. Вроде так:
Код: plaintext
1.
2.
SELECT Name
FROM MSysObjects AS O
ORDER BY Name='Tables', Name='Forms', Name='Reports';
С другой стороны т.к. здесь использовано единственное поле "Name", то можно здесь использовать IN и так:
Код: plaintext
1.
2.
SELECT Name
FROM MSysObjects AS O
ORDER BY Name IN ('Tables', 'Forms', 'Reports');
Но только в таком случае порядок следования записей будет не так, как в предыдущих запросах, т.е. не 'Tables', 'Forms', 'Reports', а 'Forms', 'Reports', Tables' (т.е. сами значения также будут отсортированы).

Есть ещё 1 нюанс: если таблица не "родная" для Access, а линкованная через ODBC (скажем таблица SQL Server), то такой номер не проходит, произойдёт ошибка:
Код: plaintext
1.
2.
SELECT Customer
FROM dbo_Customer
ORDER BY Customer IN ('Firma X', 'Firma Y', 'Firma Z');
[Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near the keyword IN ...
В таком случае специально нужно использовать функцию, которая отсутствует на стороне SQL Server, и тогда запрос будет работать на УРА:
Код: plaintext
1.
2.
SELECT Customer
FROM dbo_Customer
ORDER BY Nz(Customer) IN ('Firma X', 'Firma Y', 'Firma Z');
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37364704
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот здесь показан способ перехвата нажатия на кнопку меню. В качестве примера показан случай перехвата сортировки:
Код, который ловит событие нажатие кнопки сортировки


1. включите ссылку на библиотеку офис
2. в начале модуля формы :

Private WithEvents SortACBtn As Office.CommandBarButton
Private WithEvents SortDeBtn As Office.CommandBarButton

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Private Sub SortACBtn_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)  
    On Error Resume Next
    'CancelDefault = True - если вместо сортировки своя процедура'  
    MsgBox "Сортировка по возрастанию "  
End Sub
 
Private Sub SortDeBtn_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)  
    MsgBox "Сортировка по Убыванию "  
End Sub
 
Private Sub Form_Load()  
    Set SortACBtn = CommandBars.FindControl(id:= 210 )  
    Set SortDeBtn = CommandBars.FindControl(id:= 211 )  
End Sub

Там же имеется таблица с указанием ID контролов меню.
Я по аналогии попробовал блокировать FIND (найти), т.е. если пользователь захочет найти запись, то я программно хочу заменить "Поиск" на "Фильтр", ибо как известно поиск работает значительно медленнее чем фильтр.
Но почему-то код, прекрасно блокирующий сортировку, не хочет блокировать поиск.
Что здесь не так?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Private WithEvents FindBtn As Office.CommandBarButton

Private Sub FindBtn_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
    On Error Resume Next
    CancelDefault = True
    MsgBox "Тест."
End Sub

Private Sub Form_Load()
    Set FindBtn = CommandBars.FindControl(Id:= 5905 )  ' Здесь также попробовал 141
End Sub
Т.е. если пользователь захочет нажать на Ctrl+F или использовать меню "Правка" ==> "Найти...", то здесь хотелось бы получить сообщение "Тест".
Видимо здесь проблема с Id контрола. Как найти правильный Id?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37364739
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С id=141 клик кнопки меню отлавливает, а комбинацию Ctrl+F - фиг. (А2003)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37365102
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nord-woolfС id=141 клик кнопки меню отлавливает, а комбинацию Ctrl+F - фиг. (А2003)
Thank you! :-))

Ну тогда сделаю 141 для перехвата меню и параллельно буду перехватывать комбинацию клавиш Ctrl + F.

Ещё 1 вопрос: можно ли переделать данный код так, чтобы возможно было позднее связывание, т.е. без подключения к MS Office?
Пробовал разные варианты, но что-то у меня не получается.


P.S. А как обстоят дела в А2007 и в А2010? Был бы признателен ежели кто-нибудь напишет будет ли работать данный код в этих версиях.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37365151
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,
С подпиской на события позднее связывание не годится.
Нужна типизированная переменная соответствующего класса.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37370747
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если хотим узнать версию Windows, вызвав диалоговое окно "About", то можем использовать вот такой код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Private Declare Function ShellAbout _
        Lib "shell32.dll" Alias "ShellAboutA" ( _
        ByVal hWnd As Long, _
        ByVal szApp As String, _
        ByVal szOtherStuff As String, _
        ByVal hIcon As Long) As Long

Private Sub ShowAbout()
    ShellAbout  0 &, "", "",  0 &
End Sub


Оказывается в данном диалоговом окне можно кое-что добавить. Что то вроде этого:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Private Declare Function ShellAbout _
        Lib "shell32.dll" Alias "ShellAboutA" ( _
        ByVal hWnd As Long, _
        ByVal szApp As String, _
        ByVal szOtherStuff As String, _
        ByVal hIcon As Long) As Long

Private Sub ShowAbout()
    ShellAbout _
         0 &, _
        "Заголовок и 1-строка", _
        "Здесь напишем какой-нибудь текст, который будет " & _
            "выходить где-то в середине." & vbCrLf, _
         0 &
End Sub


Правда маловато текста умещается. Для заголовка и первой строки - всего лишь 1 строка, а для "середины" - 2 строки. :)

Здесь же можно ещё добавить иконку.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Private Declare Function ShellAbout _
        Lib "shell32.dll" Alias "ShellAboutA" ( _
        ByVal hWnd As Long, _
        ByVal szApp As String, _
        ByVal szOtherStuff As String, _
        ByVal hIcon As Long) As Long
Private Declare Function LoadIcon _
        Lib "user32.dll" Alias "LoadIconA" ( _
        ByVal hInstance As Long, _
        ByVal lpIconName As Long) As Long

Private Sub ShowAbout()
    ShellAbout _
         0 &, _
        "Что это такое?", _
        "Test is test!" & vbCrLf, _
        LoadIcon( 0 &,  32514 &)
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37371966
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

А для чего это? Просто интересно, подумал, подумал и не нашёл применения.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37372017
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvk,

Просто "спортивный интерес". Оказывается и такое возможно. :))
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37372231
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть 1 топик: Вопросы по форматированию полей .
Там вопрос № 1 гласит так:
В "Word"е имеется возможность выравнивания текста по ширине (в VBA ".ParagraphFormat.Alignment = wdAlignParagraphJustify"). В "Access"е также имеется свойство полей "Выравнивание текста" (TextAlign), где можно присвоить значение 4 (Distribute), после чего текст будет выровнен по ширине. Но имеется один недостаток: если последняя строка состоит из 1 или 2 слов, то Access расширит текст чуть ли не по буквам. А это в официальных документах (таких как контракт) не допустимо!
Как же сделать так, чтобы последнюю строку "Access" не трогал так же как в "Word"е?

В этом топике есть пост nord-wolf 9510505 , где в приложенном файле имеется код, который и расширяет текст. Однако есть небольшие недостатки:
I) если текст имеет перевод строки (Chr(13) + Chr(10)), то выглядит отчёт немного не так как надо;
II) высота поля должна быть неизменной, ну а если в деталях отчёта будет выходить несколько записей и если высота полей нефиксированная, то в отчёте будет выходить либо пустота между записями (если мы увеличили с запасом высоту поля), либо "пропадают" строки (что конечно же не допустимо). Проблема в том, что если свойство поля "Visible" = False, то высота поля станет неизменной даже если свойство "Расширение" (CanGrow) имеет значение "Да".
2-проблему можно решить только в том случае, если сделать фон и шрифт поля прозрачным и тогда можно будет свойство поля "Вывод на экран" (Visible) указать как true. К сожалению, я пока не смог решить это. А вот для того, чтобы решить 1-проблему я немного изменил код nord-wolf (главное изменение: я не стал расширять текст, а расширил пробелы между текстами как это делает Word) и у меня получился такой вариант:
Этот код можно разместить в модуле.
Код: 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.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
' Объявляем модульные переменные для расширения текста в Textbox по ширине _
  на подобие MS Word.
Private MaxWidth As Single  ' для фиксации длины текстового поля
Private sngX As Single, sngY As Single ' для определения координаты

Const SP As String = " " ' разделитель слов

' Идея процедуры заключается в следующем: _
  текстовое поле должно быть скрытым (т.е. свойство Visible = False), оно _
  необходимо нам разве что для измерения текста, а сам текст будет _
  воссоздан с помощью метода "Print" объекта "Report".
Public Sub TextAlign(Rpt As Access.Report, TextboxName As String)
    Dim ArrWords As Variant ' для массива строк
    Dim strPrint As String, strTemp As String
    Dim i As Integer
    
    With Rpt.Controls.Item(TextboxName)
        If IsNull(.Value) = True Or Len(.Value) =  0  Then Exit Sub
        ' Распределяем текст поля на массив строк с помощью функции "Split" и при _
          этом не укажем параметр функции "limit". Из-за отсутствия параметра _
          "limit" получим ровно столько элементов массива, сколько пробелов в _
          тексте +  1 .
        ArrWords = Split(Replace(.Value, vbCrLf, SP & Chr( 13 ) & SP), SP)
        
        ' Максимальная длина строк не может быть больше ширины поля. Здесь следует _
          "запомнить" ширину поля, чтобы в условиях IF можно было сравнивать ширину _
          текста.
        MaxWidth = .Width
        
        ' Здесь зафиксируем координаты текстового поля.
        sngX = .Left
        sngY = .Top
        
        ' Чтобы точно измерить длину текста с помощью метода "TextWidth" _
          следует свойства шрифта текстового поля присвоить свойствам шрифта _
          самого отчёта.
        Rpt.FontName = .FontName
        Rpt.FontSize = .FontSize
        Rpt.FontBold = .FontBold
        Rpt.FontItalic = .FontItalic
    End With
    
    ' Теперь прокручиваем массив и обратно собираем слова
    For i =  0  To UBound(ArrWords)
        strPrint = strPrint & ArrWords(i) & SP
        
        If i < UBound(ArrWords) Then
            ' Если текст содержит перевод строки, т.е. Chr(13), _
              то следует разбить на  2  текста и распечатать отдельно. _
              Иначе отчёт будет выглядит непрезентабельно. Поэтому _
              проверяем имеется ли символ Chr( 13 )
            If ArrWords(i +  1 ) <> Chr( 13 ) Then
                ' Добавив очередное слово из массива проверяем длину текста
                strTemp = strPrint & ArrWords(i +  1 )
                If Rpt.TextWidth(strTemp) > MaxWidth Then
                    ' Полученный текст больше длины текстового поля. Поначалу _
                      убираем правый, крайный пробел.
                    strPrint = RTrim$(strPrint)
                    ' Теперь с помощью процедуры "PrintText" печатаем текст. _
                      Необходимо передать процедуре количество пробелов для _
                      параметра "SpacesQuantity", чтобы процедура могла чуть-чуть _
                      расширить пробелы, чтобы выровнить текст. Для этого идеально _
                      подходит "i". Если i =  0 , то это первое слово и _
                      соответственно пробела пока нет. А если i =  1 , то слов  2  и _
                      соответственно пробел  1  и т.д.
                    PrintText Rpt, strPrint, True
                    strPrint = ""
                    strTemp = ""
                End If
            Else
                strTemp = RTrim$(strTemp)
                PrintText Rpt, strTemp, False
                strPrint = ""
                strTemp = ""
                i = i +  1 
            End If
        Else
            ' Если процедура дошла до этой точки, то это означает, что _
              мы дошли до последнего элемента массива. Здесь также _
              убираем крайний правый символ.
            strPrint = RTrim$(strPrint)
            ' Запускаем процедуру "PrintText"
            If Len(strPrint) >  0  Then
                PrintText Rpt, strPrint, False
            End If
            strPrint = ""
            strTemp = ""
        End If
    Next i
End Sub
Private Sub PrintText(Rpt As Access.Report, strPrint As String, ExtendText As Boolean)
    ' Процедура не расширяет все символы текста, как это делает Access, а _
      расширяет пробелы, как это делает Microsoft Word. Так более красивее _
      выглядят отчёты.
    Dim ArrWords As Variant, AddlSpace As Single, x As Single, i As Byte
    
    If Len(strPrint) =  0  Then Exit Sub
    
    ArrWords = Split(strPrint, SP)
    ' А если количество пробелов указано, то следует найти недостающее _
      пространство (т.е. разница между текстом "strPrint" и длиной _
      текстового поля - maxWidth) и поделить на количество пробелов. _
      При распечатке между слов следует добавить полученное число, _
      чтобы ровномерно расширить пробелы.
    If UBound(ArrWords) >  0  And ExtendText = True Then
        AddlSpace = (MaxWidth - Rpt.TextWidth(strPrint)) / UBound(ArrWords)
    End If
    x = sngX
    ' Заново прокручиваем массив строк, но на этот раз чтобы распечатать.
    For i =  0  To UBound(ArrWords)
        ' Следует определиться с координатами текста
        Rpt.CurrentX = x
        Rpt.CurrentY = sngY
        Rpt.Print ArrWords(i)
        x = x + Rpt.TextWidth(ArrWords(i) & SP) + AddlSpace
    Next i
    
    ' Для следующей строки следует вертикаль сдвинуть вниз.
    sngY = sngY + Rpt.TextHeight(strPrint)
End Sub

А в модуле отчёта можно указать примерно такой код
Код: plaintext
1.
2.
3.
Private Sub Details_Format(Cancel As Integer, FormatCount As Integer)
    TextAlign Me, "Text1"
    TextAlign Me, "Text2"
End Sub
Здесь "Text1" и "Text2" название полей textbox.


P.S. Код в принципе рабочий. Как только смогу решить и 2-проблему выложу здесь.
Наверное Бенедикт или кто-то ещё из экспертов знает как сделать фон поля и шрифт сделать прозрачным, а не белым. Если подскажите как это сделать, был бы признателен. :)

И ещё! Спасибо nord-wolf за его код.
Если у кого-то более "продвинутый код", please поделитесь!
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37379826
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не помню откуда, но как то мне попался код, который запрещает открытие одной и той же базы 2 раза. А код достаточно простой, многократно использовал в разных проектах и ничего, работает. :)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Dim FirstRunnedApp As Object, byteCheck As Byte

Set FirstRunnedApp = GetObject(CurrentProject.FullName)
If Application.hWndAccessApp <> FirstRunnedApp.hWndAccessApp Then
    byteCheck = Eval("MsgBox(""ОШИБКА!!!@Нельзя открывать базу данных 2 и более раза!!!@""," & _
        vbExclamation & ",""Системная ошибка!"")")
    FirstRunnedApp.DoCmd.RunCommand  10   ' acCmdAppMaximize = 10
    Set FirstRunnedApp = Nothing
    Application.Quit
End If
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37409030
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бывают случаи, когда в подчинённой таблице необходимо ввести не все значения ключевого поля главной таблицы, а избранные. В таких случаях часто в главной таблице создают дополнительное поле - некий признак: если признак соответствует каким-то требованиям, то значения ключевого поля только данной записи может быть в подчинённой таблице.
Чтобы было более понятно приведу пример:
Допустим есть таблица "tblCustomer", где ключевое поле "CustomerID". Есть также подчинённая таблица "tblBonus", где также имеется поле "CustomerID", куда необходимо ввести код не любого клиента, а только "VIP" клиентов. В таких случаях часто программисты создают дополнительное логическое поле "VIP" в таблице "tblCustomer" и создают Check Constraint (или триггер если таблицы находятся в "реальных" РСУБД), чтобы контролировать ввод клиентов из категории "VIP". А в Access многие вообще не возятся с Check Constraint, а в включают проверку на событие BeforeUpdate.

А существует ли другой способ без Check Constraint, триггеров и проверок на событие BeforeUpdate, но чтобы "железно" гарантировать ввод избранных значений ключевого поля (например, только VIP клиентов)?
Оказывается есть и для этого зачастую даже не требуется создание отдельного поля - признак в главной таблице. Итак, следует создать дополнительную таблицу "tblVIP", где будет единственное поле "CustomerID" и необходимо связать с главной таблицей "tblCustomer" по принципу "один к одному", при этом таблица "tblCustomer" должна находиться "левее". В таблицу "tblVIP" будем вводить код только VIP клиентов. А подчинённую таблицу "tblBonus" необходимо связать не с главной таблицей "tblCustomer", а с таблицей "tblVIP".
Вот теперь без всяких Check Constraint, "триггеров" и проверок на событие BeforeUpdate "железно" можем гарантировать "избранных" значений ключевого поля.

P.S. Связь "1 к 1" редко бывает полезным, но этот случай пожалуй исключение.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37414662
Komil_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Часто на форуме спрашивают как перевернуть текст на 90 градусов. (Сам тоже как-то спрашивал :), но теперь-то знаю как это просто.)
В Аксессе есть конечно свойство "По вертикали", но оно переворачивает текст на 270 градусов.
Как же всё-таки перевернуть на 90 градусов?
Как правило, переворачивать текст следует в заголовках столбцов отчёта (т.е. в надписях, находящихся в верхнем колонтитуле или же в заголовке отчёта). А в самих деталях отчёта редко такое требуется. Самый простейший способ это создание нужного заголовка в виде таблицы в MS Excel. После этого просто копируем таблицу и в отчете Аксесса в режиме конструктора в верхнем колонтитуле или же в заголовке отчёта вставим из буфера обмена.
Всё просто и ни одной строчки кода! :)
Есть конечно сложные коды Лебенса (мне посоветовали тогда именно их 9504909 ), но зачем когда имеется самый простой способ. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37414688
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Komil_,

а вот тут можно и спотыкнуться, когда параметры страницы менять будешь
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428353
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я раньше думал, что основное преимущество ADO перед DAO заключается в универсальности подключения к любой СУБД, находясь где угодно. Да хоть в Excel'е или в Word'е можем подключаться к Oracle, MySQL и т.п., а не только Access или SQL Server. Я раньше полагал, что DAO предназначен только для работы в Access и минуя ее не может подключится к другим СУБД. В смысле в Access'е создаём линкованную таблицу или запрос к серверу и только потом можем работать в других СУБД. Но как я понял позже, я ошибся, DAO тоже умеет работать с другими СУБД, минуя Access, главное - на клиентском компьютере должны быть соответствующие драйверы. Ещё одним большим сюрпризом для меня стало то, что объект RecordSet в DAO умеет работать и "чужим" синтаксисом (словно запрос к серверу), а не только синтаксисом Jet SQL. Но только для этого придётся "колдовать" и "шаманить" слегка. :)
Из-за чистого спортивного интереса стал экспериментировать в DAO.
Вот примерчик как можно подключиться к SQL Server (данный код можно использовать и в Excel'е):
Код: 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.
' Можно создать текст подключения через DSN
' Public Const ODBC As String = "ODBC;DSN=MyDSN";Database=MyDataBase;"
' Можно создать текст прямого подключения к серверу
Public Const ODBC As String = "ODBC;DRIVER=SQL Server;SERVER=MyServer,1433;" & _
    "DATABASE=MyDatabase;Trusted Connection=Yes;"

Sub Test()
    Dim Wrk     As DAO.Workspace
    Dim Cnnt    As DAO.Connection
    Dim DB      As DAO.Database
    Dim xQuery  As DAO.QueryDef
    Dim RecSet  As DAO.Recordset
    Dim strSQL  As String
    
    strSQL = "SELECT CAST(1.5 AS Int) AS Test"
    ' Если использовать OpenDatabase, то объект Recordset не сможет
    ' использовать напрямую синтаксис SQL Serverа, в таком случае
    ' придётся обратиться через запрос к серверу как в данном примере.
    Set DB = DBEngine.OpenDatabase("", _
        dbDriverCompleteRequired, True, ODBC)
    Set xQuery = DB.CreateQueryDef("")
    xQuery.Connect = ODBC
    xQuery.Sql = strSQL
    Set RecSet = xQuery.OpenRecordset
    MsgBox RecSet.Fields(0) & vbCrLf & _
        DB.Name & vbCrLf & _
        DB.Connect

    ' Чтобы "научить" Recordset к "чужому" синтаксису (словно запрос к
    ' серверу) придётся идти другим путём.
    Set Wrk = DBEngine.CreateWorkspace("", "", "", dbUseODBC)
    Set Cnnt = Wrk.OpenConnection("", dbDriverCompleteRequired, True, ODBC)
    Set RecSet = Cnnt.OpenRecordset(strSQL)
    MsgBox RecSet.Fields(0) & vbCrLf & _
        Cnnt.Database.Name & vbCrLf & _
        Cnnt.Connect
    Set Wrk = Nothing
    ' Нюанс: если обнулить объектную переменную Wrk, т.е. после
    ' "Set Wrk = Nothing" "Cnnt.Connect" вернёт ошибку!
    ' Поэтому вот этот код уже нельзя использовать!
    ' Debug.Print Cnnt.Connect
    
    Set Cnnt = Nothing
    Set RecSet = Nothing
    Set xQuery = Nothing
    Set DB = Nothing
End Sub

Возникает вопрос: а в чём всё-таки бесспорное преимущество ADO от DAO? Что же умеет ADO чего не умеет DAO?
Я знаю только то, что ADO "почти всё" умеет в стандарте ANSI92 SQL даже если сама база не переведена в этот стандарт (т.е. умеет запускать некоторые запросы на управления, которых DAO не может запускать без перехода в этот стандарт).
Ну и сам Microsoft вроде бы грозился убрать DAO в будущих версиях, мол устаревшая технология. По крайнем мере в А2007 пока DAO жив (из-за не имения А2010 не знаю как там).
А ещё в чём же преимущество?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428524
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren.......................
Возникает вопрос: а в чём всё-таки бесспорное преимущество ADO от DAO? Что же умеет ADO чего не умеет DAO?
Я знаю только то, что ADO "почти всё" умеет в стандарте ANSI92 SQL даже если сама база не переведена в этот стандарт (т.е. умеет запускать некоторые запросы на управления, которых DAO не может запускать без перехода в этот стандарт).
Ну и сам Microsoft вроде бы грозился убрать DAO в будущих версиях, мол устаревшая технология. По крайнем мере в А2007 пока DAO жив (из-за не имения А2010 не знаю как там).
А ещё в чём же преимущество?
Да какой смысл разбирать две устаревшие технологии доступа к данным? Из спортивного интереса если только?
Могу подкинуть одно преимущество ADO (если конечно, не ошибаюсь): multiple recordsets. Эта возможность мне помогла добиться выполнения скрипта из нескольких SQL-команд в Jet-e, когда создавал для себя нечто вроде Query Analyzer.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428857
Guest33
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если не ошибаюсь, второй вариант ОДБС подключения (через опенконнект) называется ODBC direct и в А2010 не поддерживается. Обнаружил, когда для пробы переводил свою программу с А2003 на А2010
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428882
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sator ArepoДа какой смысл разбирать две устаревшие технологии доступа к данным?
Разве технология ADO (ADODB/ADOX) уже устарела? У нее есть альтернатива?

Sator ArepoМогу подкинуть одно преимущество ADO (если конечно, не ошибаюсь): multiple recordsets.
Вы имеете ввиду NextRecordset или что-то другое?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428921
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenSator ArepoДа какой смысл разбирать две устаревшие технологии доступа к данным?
Разве технология ADO (ADODB/ADOX) уже устарела? У нее есть альтернатива?

Sator ArepoМогу подкинуть одно преимущество ADO (если конечно, не ошибаюсь): multiple recordsets.
Вы имеете ввиду NextRecordset или что-то другое?
Да, NextRecordset.
Насчет "устаревшие" - может и погорячился. Альтернатив DAO/ADO для Аксесса в любом случае нет. Дык и Аксесс уже дедушка на пенсии - ADO.Net не для него.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428953
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то и в DAO есть NextRecordSet.

Значит единственное преимущество (по крайнем мере другого пока не вижу) - это умение запускать спец запросов на управление (например, создание Check Constraint).
Ну если ошибаюсь и всё-таки есть что-то, please напишите.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428958
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВообще-то и в DAO есть NextRecordSet.

Значит единственное преимущество (по крайнем мере другого пока не вижу) - это умение запускать спец запросов на управление (например, создание Check Constraint).
Ну если ошибаюсь и всё-таки есть что-то, please напишите.
А чего желтым цветом-то? Спасибо, я не знал - т.к. необходимости не было, а когда начинал изучать Аксесс, вовсю пропогандировался ADO.
Одно из многочисленных обсуждений
http://www.accessmonster.com/Uwe/Forum.aspx/access-ado/1780/ADO-vs-DAO
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428972
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВообще-то и в DAO есть NextRecordSet.

Значит единственное преимущество (по крайнем мере другого пока не вижу) - это умение запускать спец запросов на управление (например, создание Check Constraint).
Ну если ошибаюсь и всё-таки есть что-то, please напишите.
вот еще интересное обсуждение
http://blogs.msdn.com/b/michkap/archive/2007/07/13/3849288.aspx
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37428991
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sator Arepo,

Спасибо! Хорошие ссылки. Читаю и изучаю.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37435722
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы использовать регулярные выражения я создал такую функцию:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Public Function RegularExp(strPattern As String, strText As String) As String
    Static objRegExp As Object
    
    If objRegExp Is Nothing Then
        Set objRegExp = CreateObject("VBScript.RegExp")
        objRegExp.Global = True
    End If
    objRegExp.Pattern = strPattern
    RegularExp = objRegExp.Replace(strText, "")
End Function
И действительно, если мне нужно выбрать все цифры из определённого текста, то получаю вот такой результат:
Код: plaintext
1.
?RegularExp("[^0-9]", "qweqw676q aw76^,eабвгд")
 67676 
А вот если мне нужно выбрать из текста только английские буквы, то попробовал так:
Код: plaintext
1.
?RegularExp("[^A-z]", "qweqw676q aw76^,eабвгд")
qweqwqaw^e
Поначалу не понял, что здесь делает "^" ? Попробовал чуть-чуть по другому задать шаблон.
Код: plaintext
1.
?RegularExp("[^A-Za-z]", "qweqw676q aw76^,eабвгд")
qweqwqawe
Оказывается по умолчанию объект RegExp чувствительный к регистру, да и как-то странно "чувствительный". Никак не ожидал, что в диапазоне "A-z" окажется символ "^". А потом понял, что в диапазоне "A-z" также находятся такие символы как "[\]^_`".
А вот в VBA и в Jet SQL эти символы не входят в данный диапазон.
Код: plaintext
1.
2.
3.
SELECT
    '123^456' Like '*[A-z]*' AS Test1,
    '12z^456' Like '*[A-z]*' AS Test2,
    '[\]^_`' Like '*[A-z]*' AS Test3;
Результат запроса:
Код: plaintext
 0 , - 1 ,  0 
У объекта RegExp есть ещё одно свойство - " IgnoreCase ", которое как раз и рассчитано на "чувствительность к регистру".
Пробую так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Public Function RegularExp(strPattern As String, strText As String) As String
    Static objRegExp As Object
    
    If objRegExp Is Nothing Then
        Set objRegExp = CreateObject("VBScript.RegExp")
        objRegExp.Global = True
        objRegExp.IgnoreCase = True
    End If
    objRegExp.Pattern = strPattern
    RegularExp = objRegExp.Replace(strText, "")
End Function

Код: plaintext
1.
?RegularExp("[^A-Z]", "[\]^_`{}Aa")
Aa
Теперь чтобы не попали "случайные" символы я должен указать диапазон "A- Z " или же " a-z ".
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462288
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Столкнулся как-то с одной проблемой: есть таблица с несколькими полями, из которых в соответствии с требованиями бизнес правил 4 поля (условно назову Field1, Field2, Field3, Field4) должны были всегда либо заполнены, либо пустые, т.е. частичное заполнение не допускается.
Тогда я на стороне SQL Server создал вот такой Check Constraint:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
ALTER TABLE dbo.Table1 WITH CHECK ADD  CONSTRAINT [CK_Table1] CHECK 
    ((CASE WHEN Field1 Is Null THEN  1  ELSE  2  END) +
    (CASE WHEN Field2 Is Null THEN  2  ELSE  3  END) +
    (CASE WHEN Field3 Is Null THEN  3  ELSE  4  END) +
    (CASE WHEN Field4 Is Null THEN  4  ELSE  1  END) =  10 )
GO

ALTER TABLE dbo.Table1 CHECK CONSTRAINT [CK_Table1]
GO
А в "родных" таблицах MS Access этот же Check Constraint выглядел бы примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Sub SetCheckConstraint()
    Dim strSQL AS String

    strSQL = "ALTER TABLE Table1 ADD CONSTRAINT CK_Table1 CHECK (" & _
        "IIf(IsNull(Field1), 1, 2) + IIf(IsNull(Field2), 2, 3) + " & _
        "IIf(IsNull(Field3), 3, 4) + IIf(IsNull(Field4), 4, 1) = 10);"
    CurrentProject.Connection.Execute strSQL
End Sub

Т.е. идея данного Check Constraint состоит в том, что в случае заполнения всех полей или наоборот не заполнения всегда получим в сумме 10, а если хотя бы одно поле не заполнено, тогда как остальные поля заполнены, то уже сумма никак не получится 10.
Конечно можно было бы переписать данный код и таким образом:
Код: plaintext
1.
2.
3.
strSQL = "ALTER TABLE Table1 ADD CONSTRAINT CK_Table1 CHECK (" & _
    "IIf(IsNull(Field1), 1, 0) + IIf(IsNull(Field2), 1, 0) + " & _
    "IIf(IsNull(Field3), 1, 0) + IIf(IsNull(Field4), 1, 0) IN (0, 4));"
End Sub
Но насколько мне известно IN работает точно также как и OR. И я решил обойтись без него. :)

Есть ли у кого-нибудь другая более "продвинутая" идея, более красивое решение?

Вот пример красивого решения другой проблемы:
если нам нужно отфильтровать данные за текущий месяц, то можно использовать вот такой код а запросах:
Код: plaintext
WHERE Month([SomeDate]) = Month(Date()) AND Year([SomeDate]) = Year(Date())
или такой:
Код: plaintext
WHERE Format([SomeDate], "yyyymm") = Format(Date(), "yyyymm")
Но мне больше нравится вот такой вариант (на днях в каком-то топике полином показывал)
Код: plaintext
WHERE DATEDIFF("m", [SomeDate], Date()) =  0 

Вот и думаю, а может действительно есть более "красивый" и эффектный Check Constraint?
P.S. Вопрос чисто из разряда "спортивный интерес". :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462336
Фотография qwrqwr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenТ.е. идея данного Check Constraint состоит в том, что в случае заполнения всех полей или наоборот не заполнения всегда получим в сумме 10, а если хотя бы одно поле не заполнено, тогда как остальные поля заполнены, то уже сумма никак не получится 10.

Можно сэкономить 8 вызовов функций (4 раза IIF, 4 раза IsNull):
Код: plaintext
1.
strSQL = "ALTER TABLE Table1 ADD CONSTRAINT CK_Table1 CHECK (" & _
    "(([Field1] Is Null)+([Field2] Is Null)+([Field3] Is Null)+([Field4] Is Null)) In (0,-4));"
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462367
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwrqwr,

Хороший вариант. :)
А вот в SQL Server наверное без CASE WHEN ... THEN ... перевести нельзя?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462377
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

так в последнем варианте ведь нет iif или case.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462388
Фотография qwrqwr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenА вот в SQL Server наверное без CASE WHEN ... THEN ... перевести нельзя?Напрямую нельзя, т.к. там нет логического типа данных, а в Access - есть, да еще и участвующий в неявных преобразованиях (в 0 или -1).
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462523
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenСтолкнулся как-то с одной проблемой: есть таблица с несколькими полями, из которых в соответствии с требованиями бизнес правил 4 поля (условно назову Field1, Field2, Field3, Field4) должны были всегда либо заполнены, либо пустые, т.е. частичное заполнение не допускается.
Тогда я на стороне SQL Server создал вот такой Check Constraint:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
ALTER TABLE dbo.Table1 WITH CHECK ADD  CONSTRAINT [CK_Table1] CHECK 
    ((CASE WHEN Field1 Is Null THEN  1  ELSE  2  END) +
    (CASE WHEN Field2 Is Null THEN  2  ELSE  3  END) +
    (CASE WHEN Field3 Is Null THEN  3  ELSE  4  END) +
    (CASE WHEN Field4 Is Null THEN  4  ELSE  1  END) =  10 )
GO

ALTER TABLE dbo.Table1 CHECK CONSTRAINT [CK_Table1]
GO
А в "родных" таблицах MS Access этот же Check Constraint выглядел бы примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Sub SetCheckConstraint()
    Dim strSQL AS String

    strSQL = "ALTER TABLE Table1 ADD CONSTRAINT CK_Table1 CHECK (" & _
        "IIf(IsNull(Field1), 1, 2) + IIf(IsNull(Field2), 2, 3) + " & _
        "IIf(IsNull(Field3), 3, 4) + IIf(IsNull(Field4), 4, 1) = 10);"
    CurrentProject.Connection.Execute strSQL
End Sub

Т.е. идея данного Check Constraint состоит в том, что в случае заполнения всех полей или наоборот не заполнения всегда получим в сумме 10, а если хотя бы одно поле не заполнено, тогда как остальные поля заполнены, то уже сумма никак не получится 10.
Конечно можно было бы переписать данный код и таким образом:
Код: plaintext
1.
2.
3.
strSQL = "ALTER TABLE Table1 ADD CONSTRAINT CK_Table1 CHECK (" & _
    "IIf(IsNull(Field1), 1, 0) + IIf(IsNull(Field2), 1, 0) + " & _
    "IIf(IsNull(Field3), 1, 0) + IIf(IsNull(Field4), 1, 0) IN (0, 4));"
End Sub
Но насколько мне известно IN работает точно также как и OR. И я решил обойтись без него. :)

Есть ли у кого-нибудь другая более "продвинутая" идея, более красивое решение?
...

Термины вроде "красивое" и "изящное" плохи тем, что предполагают наличие развитых навыков мышления и надежную систему оценок среди любителей красоты.
Разумно понизить градус и заменить красивое на прикольное.
Есть ли варианты прикольнее?
Если 4 поля числовые, то все заполнены можно сформулировать так
(sgn(a)*sgn(b)*sgn(c)*sgn(d)) is not null
(в расчете на то, что sgn в jet сможет принять null-значения)
а все пропущены так
(a+b+c+d) is Null

для строковых полей можно записать что-то такое
все заполнены
(sgn(len(a))*sgn(len(b))*sgn(len(c))*sgn(len(d))) is null
все пропущены
(a+b+c+d) is Null
или
(len(a)+len(b)+len(c)+len(d)) is Null

в принципе, вариант для строк м.б. применим и для чисел.

Выбирая между прикольными и нормальными вариантами можно руководствоваться
1)решением о том, какой из вариантов наиболее прямо выражает намеренеия создателя
2) какой из вариантов выглядит привлекательнее с точки зрения последующего сопровождения.
как-то так...

ясно ли читателю, почему создатель написал
(sgn(a)*sgn(b)*sgn(c)*sgn(d)) is not null

а не
(a*b*c*d) is not null
?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462525
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
опечатка, д.б. так

все заполнены
(sgn(len(a))*sgn(len(b))*sgn(len(c))*sgn(len(d))) is not null
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462567
ё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ё
Гость
врядли это чем-то лучше уже предложенного ... просто - "в копилку" ))
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
create table #t (f1 int, f2 int, f3 int, f4 int)


alter table #t add check 
(
	isnull(cast(f1 as bit), 0 ) & isnull(cast(f2 as bit), 0 ) & isnull(cast(f3 as bit), 0 ) & isnull(cast(f4 as bit), 0 )= 1 
	or
	isnull(cast(f1 as bit), 0 ) | isnull(cast(f2 as bit), 0 ) | isnull(cast(f3 as bit), 0 ) | isnull(cast(f4 as bit), 0 )= 0 	
)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
insert into #t
select  1 ,  2 ,  3 ,  4 

insert into #t
select  1 ,  2 ,  3 , null

insert into #t
select  1 ,  2 , null, null

insert into #t
select  1 , null, null, null

insert into #t
select null, null, null, null

--
select * from #t

--
drop table #t
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462598
Фотография qwrqwr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ёврядли это чем-то лучше
хуже =)
Код: plaintext
1.
insert into #t
select  0 ,  0 , null,  0 
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462611
ё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ё
Гость
qwrqwrёврядли это чем-то лучше
хуже =)
Код: plaintext
1.
insert into #t
select  0 ,  0 , null,  0 

хмм, даа ))
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462612
:-Q
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
:-Q
Гость
А чем решение в лоб хуже
Код: plaintext
1.
2.
3.
4.
5.
alter table #t add check 
(
	(f1 is null and f2 is null and f3 is null and f4 is null)
	or
	(f1 is not null and f2 is not null and f3 is not null and f4 is not null)
);
?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462621
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А чем решение в лоб хуже
Код: plaintext
1.
2.
3.
4.
5.
alter table #t add check 
(
	(f1 is null and f2 is null and f3 is null and f4 is null)
	or
	(f1 is not null and f2 is not null and f3 is not null and f4 is not null)
);
?


Так чересчур понятнее получается, не по "индусский".
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462623
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А чем решение в лоб хуже
Код: plaintext
1.
2.
3.
4.
5.
alter table #t add check 
(
	(f1 is null and f2 is null and f3 is null and f4 is null)
	or
	(f1 is not null and f2 is not null and f3 is not null and f4 is not null)
);
?


слишком явно выражает намерения создателя.
Противно даже сопровождать такое надменное проявление образования.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37462649
:-Q
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
:-Q
Гость
согласен.

не по-людски получилось :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474743
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как известно, Mid (Mid$) это функция, которая извлекает часть текста. Как-то мне попался код, где функция Mid "вела себя" не так, как обычная VBA функция. Mid принимала значение, а не возвращала как обычные функции (хотя в справочнике Access'а об этом тоже написано, но я как в справочнике особо не рылся до этого, поэтому для меня было полным неожиданностью этот факт). Вот примерчик:
Код: plaintext
1.
2.
3.
4.
5.
6.
Sub Test()
    Dim S As String
    
    S = "Test!!!"
    Mid(S,  5 ,  3 ) = "..."
    MsgBox S
End Sub
В результате мы получим "Test...".
Т.е. если часть символов в самом тексте надо заменить другими символами, то можно использовать Mid, но только не с правой стороны знака равенства как обычно, а с левой.
А вот Left и Right или другие текстовые функции не обладают таким "даром".
После этого случая я стал искать ещё другие функции, которые могли бы работать как с правой стороны, так и с левой стороны знака равенства (=), т.е. принимать значения, а не только возвращать. Нашёл ещё 2 функции: это Date (или VBA.Date() ) Time (или VBA.Time() ). Эти функции возвращают не только текущую дату и время, но и могут изменить дату и время компьютера (если пользователь имеет права администратора). Больше пока не нашёл встроенных функций, возвращающих и принимающих параметров.

Может быть кто-то подскажет, есть ли ещё такие функции?

Чисто экспериментально выяснил, что пользовательские функции, возвращающие некоторые виды объектных переменных (к сожалению не всех видов), обладают таким свойством. Вот примерчик из Excel'а:
Копируем значение ячейки "A1" в "A2".
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Function SomeRange(Address As String) As Range
    Set SomeRange = Range(Address)
End Function

Sub Test()
    Dim R As Range
    
    Set R = Cells( 1 ,  1 )
    SomeRange("A2") = R
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474758
ZezaM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,
без обид - чисто для справки...:))
хелпА97
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Инструкция Time
Устанавливает системное время.
Синтаксис
Time = время

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

Дополнительные сведения

Если аргумент время является строкой, инструкция Time пытается 
преобразовать ее в значение времени, используя разделители 
компонентов времени, определенные в текущей системе.  
Если указанную строку не удастся преобразовать в допустимое время, возникает ошибка.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474762
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
ZezaMstudieren,
без обид - чисто для справки...:))
Дык, вроде коллега studieren именно это и сказал...

Но зато:

studierenЧисто экспериментально выяснил, что пользовательские функции, возвращающие некоторые виды объектных переменных (к сожалению не всех видов), обладают таким свойством. Вот примерчик из Excel'а:
Копируем значение ячейки "A1" в "A2".
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Function SomeRange(Address As String) As Range
    Set SomeRange = Range(Address)
End Function

Sub Test()
    Dim R As Range
    
    Set R = Cells( 1 ,  1 )
    SomeRange("A2") = R
End Sub

Здесь ничего чудесного нет. Главное то, что объект Range имеет свойство по умолчанию Value. Поэтому если мы ставим такой объект слева от знака присваивания, то мы фактически присваиваем что-то его свойству Value. Точно так же можно поступить, например, с объектом Control.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474774
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир Саныч...
Здесь ничего чудесного нет. Главное то, что объект Range имеет свойство по умолчанию Value. Поэтому если мы ставим такой объект слева от знака присваивания, то мы фактически присваиваем что-то его свойству Value. Точно так же можно поступить, например, с объектом Control.

Добрый вечер уважаемый Саныч!
Вы не знаете почему такой эффект возможен только с теми пользовательскими функциями, которые возвращают объектный переменный? Вот если функция возвращает число, дату, текст или ещё что-то, то её уже невозможно использовать с левой стороны.
Да и что касается свойства объекта по умолчанию, я думаю Вы правы на все 100 %. :)

P.S. Цена вопроса чисто "спортивный интерес", не более того. :))
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474778
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и главный вопрос: есть ли ещё такие "универсальные" функции помимо Mid, Date и Time?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474791
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
studierenВы не знаете почему такой эффект возможен только с теми пользовательскими функциями, которые возвращают объектный переменный? Вот если функция возвращает число, дату, текст или ещё что-то, то её уже невозможно использовать с левой стороны.
Мне казалось, что я именно на этот вопрос сейчас отвечал, но попробую еще раз. Когда мы пишем оператор присваивания, в котором слева стоит объектная переменная, но в нем нет слова Set, то присваивание идет не самому объекту , а его умолчательному свойству. Если это свойство не read-only, то это работает. Даже если сам объект получен как результат обращения к функции.

studierenНу и главный вопрос: есть ли ещё такие "универсальные" функции помимо Mid, Date и Time?
Увы, не знаю. Сам пользуюсь таким образом только функцией Mid.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474800
Фотография Sator Arepo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,
MSDNVisual Basic имеет функцию Mid и оператор Mid. Оба этих элемента влияют на указанное число знаков в строке, но функция Mid возвращает знаки, в то время как оператор Mid заменяет символы. Дополнительные сведения см. в разделе Оператор Mid.

http://msdn.microsoft.com/ru-ru/library/05e63829(v=vs.90).aspx
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474829
ё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ё
Гость
Sator Arepostudieren,
MSDNVisual Basic имеет функцию Mid и оператор Mid. Оба этих элемента влияют на указанное число знаков в строке, но функция Mid возвращает знаки, в то время как оператор Mid заменяет символы. Дополнительные сведения см. в разделе Оператор Mid.

http://msdn.microsoft.com/ru-ru/library/05e63829(v=vs.90).aspx
+1
тоже самое и касательно Time / Date

Time
The Time keyword is used in these contexts:

Time Function

Time Statement

---------------
Time Function


Returns a Variant (Date) indicating the current system time.

Syntax

Time

Remarks

To set the system time, use the Time statement.

---------------------------------
Time Statement


Sets the system time.

Syntax

Time = time

The required time argument is any numeric expression, string expression, or any combination, that can represent a time.

Remarks

If time is a string, Time attempts to convert it to a time using the time separators you specified for your system. If it can't be converted to a valid time, an error occurs.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474875
just another tutor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren...
Может быть кто-то подскажет, есть ли ещё такие функции?
...
[/src]
в VBA еще Calendar

Посмотрите в просмотрщик объектов. Date и Time - там описаны не как функции, а как property.
Раз не сказано, что read-only property, значит могут как отдавать так и принимать значения.
Если для для объекта определено одновременно и свойство get и свойство set/let? то имя свойства может быть
как слева так и справа в операторе присваивания значения.

Mid с левой стороны присвоения - это "настоящий" statement.
Настоящие statement-ы являются частью языка, описаны в справке и в библиотеке типов VBA не представлены.
(
Как не представлен, например, statement
Open pathname For mode [Access access] [lock] As [#]filenumber [Len=reclength]
)

По поводу функций, возвращающих объекты, повторюсь за Санычем:
Умение оказаться с левой стороны не их собственное свойство и не свойство всех объектов вообще,
а только таких объектов, для которых заявлены "свойства по умолчанию".
Если для объекта не определено свойство по умолчанию, то возвращающая его функция не может оказаться слева.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474876
авторЕсли для объекта не определено свойство по умолчанию, то возвращающая его функция не может оказаться слева.
подразумавается - в обсуждаемом контексте не может, т.е. не может без дополнительных квалификаторов.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474886
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
just another tutor...
Если для объекта не определено свойство по умолчанию, то возвращающая его функция не может оказаться слева.
Не так категорично.
Может, но с явным указанием свойства объекта.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
'Class Module "clsItem":
Option Explicit
Public Value As Long

'Module
Public Function GetItem() As clsItem
    Static Item As New clsItem
    Set GetItem = Item
End Function

Public Sub Test()
    Debug.Print GetItem.Value
    GetItem.Value =  5 &
    Debug.Print GetItem.Value
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474887
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Долго писал, сори. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474888
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
just another tutorв VBA еще Calendar

Посмотрите в просмотрщик объектов. Date и Time - там описаны не как функции, а как property.
Раз не сказано, что read-only property, значит могут как отдавать так и принимать значения.
Если для для объекта определено одновременно и свойство get и свойство set/let? то имя свойства может быть
как слева так и справа в операторе присваивания значения.
Этак можно и до обычных переменных дойти.

Dim a As Integer
a = 8
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474896
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир Саныч... обычных переменных ...
:)
А через функцию с "обычной" переменной не "дойдем".
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474897
just another tutor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторЭтак можно и до обычных переменных дойти
можно и дойти, если это по какой-то причине плохо или хорошо.
Пока мне не удается расшифровать смысл твоего высказывания.

так написать можно
Код: plaintext
1.
Dim a As Integer
a =  8  

а так нельзя
авторDim a As Integer
8=a

и так нельзя
авторDim a As Integer
8=a

Хорошо было бы определиться - что нам необходимо сделать:
осудить самы возможность использования Date и Time в качестве приемника значения
или научиться понимать, что происходит или может происходить, когда кто-то способен выступать в качестве приемника значения.

Подвох во всей этой истории только в том, что Mid = a&b&c - не имеет ничего общего с Date = #литерал или выражение#
хотя и выглядит похожим образом
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474899
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
nord-woolfВладимир Саныч... обычных переменных ...
:)
А через функцию с "обычной" переменной не "дойдем".
Once more, please?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474900
и
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
и
Гость
автори так нельзя
автор
Dim a As Integer
8=a

подразумевалось
Dim 8 As Integer
8=a
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474902
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Владимир Саныч,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Private A As Integer

Public Function GetA() As Integer
    GetA = A
End Function

Public Sub Test()
    Debug.Print GetA
    GetA =  5 
    Debug.Print GetA
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474903
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
just another tutorможно и дойти, если это по какой-то причине плохо или хорошо.
Пока мне не удается расшифровать смысл твоего высказывания.
Мы ищем вещи, которые обычно используются справа, но допускают и использование слева, что может явиться сюрпризом для неискушенных. Функция (например, Mid) этому критерию отвечает. Переменная, даже если она является свойством объекта, - вряд ли.

just another tutorа так нельзя
авторDim a As Integer
8=a
Нет, про константы я такого не говорил. Хотя сюрприз тоже был бы, если бы.

just another tutorи так нельзя
авторDim a As Integer
8=a
У меня дежа-вю или тут действительно написано два раза одно и то же?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474904
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
иподразумевалось
Dim 8 As Integer
8=a
Ну ваще.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474905
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
nord-woolf GetA = 5
А что, кому-то здесь неизвестно, что так нельзя?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474907
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир Саныч,
А я почем знаю?
Я вот только сегодня узнал, что переменные бывают "обычными".
Наверно и "необычные" бывают.
:)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474908
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Тьфублин. Ну а как назвать переменную, чтобы было понятно, что имеется в виду именнопеременнаяанефункцияинесвойствоинеещечтонибудь?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474911
just another tutor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторПеременная, даже если она является свойством объекта, - вряд ли.

Я Вам как человек необразованный скажу.
Остановиться, оно конечно, обязательно где-то надо.
Иначе глупости не избежать.

В Vba переменная-член класса и свойство могут вести себя сходным образом,
но не являются синонимами.
Это самостоятельные конструкты с несовпадающей семантикой.

С публичными переменными-членами класса можно обходиться так, как показал nord-woolf
Визуально это не должно вызывать вероятного удивления, в отличие от удивления, представленного в цитируемом тексте
studierenВладимир Саныч...
Здесь ничего чудесного нет. Главное то, что объект Range имеет свойство по умолчанию Value. Поэтому если мы ставим такой объект слева от знака присваивания, то мы фактически присваиваем что-то его свойству Value. Точно так же можно поступить, например, с объектом Control.

Добрый вечер уважаемый Саныч!
Вы не знаете почему такой эффект возможен только с теми пользовательскими функциями, которые возвращают объектный переменный? Вот если функция возвращает число, дату, текст или ещё что-то, то её уже невозможно использовать с левой стороны.
Да и что касается свойства объекта по умолчанию, я думаю Вы правы на все 100 %. :)

P.S. Цена вопроса чисто "спортивный интерес", не более того. :))

Если я правильно понимаю, предмет удивления - в отсутствии квалификации приемника.
Тем самым в присутствии свойства по умолчанию.
Иначе просто видно глазами - кто что кому присваивает.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474912
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир Саныч,
Ну надо-же по брюзжать на ночь глядя? :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474913
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
just another tutorЯ Вам как человек необразованный
А вот это не надо, это не надо. Я тут своей необразованностью много кого переплюну.

just another tutorВ Vba переменная-член класса и свойство могут вести себя сходным образом,
но не являются синонимами.
Это понятно. Но очевидно, что свойство МОЖЕТ вести себя как переменная. Причем не где-нибудь, а в простейшем случае. Так что удивления тут не будет.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474914
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
nord-woolfВладимир Саныч,
Ну надо-же по брюзжать на ночь глядя? :)
Да!
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474919
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир Саныч... Ну а как назвать переменную, чтобы было понятно, что имеется в виду именнопеременнаяанефункцияинесвойствоинеещечтонибудь?
Может так?:
Свойство, описанное переменной
vs
Свойство описанное процедурами(процедурой) свойств.

ps. Все-все, ушел спать.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37474936
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
nord-woolfСвойство, описанное переменной
Это в ответ на "переменная, а не свойство"?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37551351
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы превратить строку в тип данных "дата" нужно использовать функцию CDate или DateValue . Но тут есть одна засада: данные функции в зависимости от региональных настроек Windows возвращают разные результаты, а иногда вообще ошибку.
Допустим, у нас есть строка в американском стиле и мы хотим в любом случае получить соответствующую дату. Я для этого создал функцию "ConvDate", где есть необязательный параметр "Style". Если в параметре указать "EN" или "English" или "US", то функция попытается преобразовать строку в дату сначала в американском стиле. Если не получится, то с помощью CDate.
Код: 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.
Function ConvDate(DateString As String, Optional Style As String) As Date
    Dim DateResult As Date
    
    On Error Resume Next
    Select Case Style
    Case "EN", "English", "US"
        If DateString Like "[#]*[#]" Then
            ConvDate = Eval(DateString)
        Else
            ConvDate = Eval("#" & DateString & "#")
        End If
        If Err.Number <>  0  Then
            ConvDate = DateValue(DateString)
        End If
    Case Else
        ConvDate = DateValue(DateString)
        If Err.Number <>  0  Then
            If DateString Like "[#]*[#]" Then
                ConvDate = Eval(DateString)
            Else
                ConvDate = Eval("#" & DateString & "#")
            End If
        End If
    End Select
End Function

А вот и результат экспериментов:
Код: plaintext
1.
2.
3.
?ConvDate("31-JAN-2011")
 31 . 01 . 2011  
?ConvDate("31-ЯНВ-2011")
 31 . 01 . 2011  
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37551580
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
(для текстов, совпадающих с текущей локалью)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Sub test()
  Dim s As String, s2 As String, s3 As String
  
  Dim d As Date, d2 As Date, d3 As String
  
  s = "12/31/2011"
  d = Format(s, "mm\/dd\/yyyy")
  
  s3 = "15-06-2011"
  d3 = Format(s3, "dd-mm-yyyy")
  
  s2 = "20 декабря 2010"
  d2 = Format(s2, "dd mmmm yyyy")
  Debug.Print d, d3, d2
End Sub

поищите - на форуме есть примеры, как подменить локаль на время выполнения процедуры
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37551773
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby(для текстов, совпадающих с текущей локалью)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Sub test()
  Dim s As String, s2 As String, s3 As String
  
  Dim d As Date, d2 As Date, d3 As String
  
  s = "12/31/2011"
  d = Format(s, "mm\/dd\/yyyy")
  
  s3 = "15-06-2011"
  d3 = Format(s3, "dd-mm-yyyy")
  
  s2 = "20 декабря 2010"
  d2 = Format(s2, "dd mmmm yyyy")
  Debug.Print d, d3, d2
End Sub

поищите - на форуме есть примеры, как подменить локаль на время выполнения процедуры

Вы наверное не поняли мой пост. Я попытался создать универсальную функцию, которая по возможности все строки в любом формате превращает в дату вне зависимости от настройки Windows. К примеру, допустим у Вас Windows настроен на русскую интерпретацию даты, но в тоже время у Вас строка на английский лад. Как Вы собираетесь преобразовать строку?
Пример:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
?ConvDate("31-December-2001")
 31 . 12 . 2001  
?ConvDate("31-Декабря-2001")
 31 . 12 . 2001  
?ConvDate("31-Декабрь-2001")
 31 . 12 . 2001 
?ConvDate("#1/15/2001#")
 15 . 01 . 2001  
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37551987
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы правы. я действительно не понял. Не рассмотрел ваш код.
Это одна сторона монеты.

Другие стороны состоят вот в чем:
1)
Вы заставили на русской локали работать
Код: plaintext
? eval("#15-June-2001#")
и
Код: plaintext
? eval("#June 15 001#")

Подразумевается, что английский язык всегда установлен.

Сможете тем же способом заставить, без установленного немецкого, правильно отработать

Код: plaintext
? eval("#15-Juni-2001#")
или
Код: plaintext
? eval("#Juni 15 2001#")
или
Код: plaintext
? eval("#Dezember 15 2001#")

2) то что
Код: plaintext
1.
2.
? eval("#05/03/2001#")
 03 . 05 . 2001  
это правдоподобно до тех пор, пока не выяснится, что создатель строки подраумевал
5 марта, а не 3 мая.

PS
Это не претензии. Ваша функция хорошая.
Другое дело, что я, как пользователь "библиотечного кода", предпочел бы
функцию с явно задаваемым форматом преобразования и, может быть, явными языковыми идентификаторами в качестве параметров.

В любом случае спасибо.
Поведение eval в этом месте любобытно и малоизвестно.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37553292
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
boobyДругое дело, что я, как пользователь "библиотечного кода", предпочел бы
функцию с явно задаваемым форматом преобразования и, может быть, явными языковыми идентификаторами в качестве параметров.

Забыл написать 1 деталь.
В SQL Server если в строке указать дату в формате 'yyyymmdd', то вне зависимости от настроек сервера всегда дата будет интерпретироваться одинаково:
Код: plaintext
SELECT CAST('20111130' AS Smalldatetime)

Такое же свойство имеется и у Access / VBA, но только чуть-чуть по другому.
Если в строке указать дату в формате "yyyy-mm-dd" (вместо "-" также допускается пробел или слеш "/"), то вне зависимости от региональных настроек функция CDate и Datevalue (да и DateAdd) возвращает ВСЕГДА одинаковую дату.
Код: plaintext
1.
2.
3.
4.
5.
?DateValue("2011 11 1")
 01 . 11 . 2011  
?CDate("2011-11-03")
 03 . 11 . 2011  
?DateAdd("d",  1 , "2011/12/1")
 02 . 12 . 2011 
А вот так уже нельзя, VBA будет ругаться:
Код: plaintext
?DateValue("2011 13 01")

P.S. Как не странно, но в FAQе об этом вообще ни слова.
И там не указана ещё одна деталь:
даты в Access / VBA можно указать и таким образом:
Код: plaintext
SELECT # 01 /JAN/ 2011 #, #February  2   2010 #, # 2011 -MAY  15 #, # 11 / 2009 /Jun#
Т.е. если название месяца указать на английском, то день, месяц, год можно указать в любом порядке. Из этих форматов чаще всего пользуюсь первым способом, т.е. формат #DD/MMM/YYYY#, т.к. полностью исключает разночтение. Думаю даже для новичков будет наиболее "читабельным". :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37726699
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы открыть отчёт в режиме предварительного просмотра и при этом сразу же задать масштаб обычно поступают так:
Код: vbnet
1.
2.
DoCmd.OpenReport "Название отчёта", acPreview
DoCmd.RunCommand acCmdZoom100


Здесь вместо "acCmdZoom100" можно также использовать другие стандартные масштабы (например acCmdZoom75 или acCmdZoom150).
А как же задать нестандартный масштаб? Ну например 125%?
Как то случайно мне попался файл, где использовался скрытое (недокументированное) свойство отчёта "ZoomControl", с помощью которого можно задать любой нестандартный масштаб.
Код: vbnet
1.
2.
DoCmd.OpenReport "Название отчёта", acPreview
Reports("Название отчёта").ZoomControl = 125


Но только есть 1 недостаток: внутри модуля отчёта этот код нельзя использовать (т.е. невозможно повесить на open или activate), только и только нужно "со стороны" сразу после OpenReport. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37741666
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Иногда бывает полезным программно "поймать событие" нажатия команды штатного меню. Например, перед сжатием базы целесообразно удалить ненужные таблицы (скажем "Ошибки вставки", "Admin - 00" и т.д.) и "временные" запросы ("Запрос1", "Запрос2" и т.п.).
Как же сделать это?

Вот здесь я написал случай преобразования MDB файла на MDE. Теперь попробую "поймать сжатие" базы.
В первую очередь конечно же не забываем включить библиотеку "Microsoft Office XX Object Library". (вместо XX нужная версия офиса).
Итак, если у нас есть скрытая форма, открывающаяся в момент старта базы, то в модуль формы пишем так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Private WithEvents CompactDB As Office.CommandBarButton

Private Sub Form_Load()
    Set CompactDB = CommandBars.FindControl(Id:=2071)
End Sub

Private Sub CompactDB_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
    On Error Resume Next
    ' Вот здесь уже пишем свой код, который выполнится раньше _
      чем штатное действия Access'а.
    ' Если нам нужно блокировать штатное действия Access, то пишем так:
    CancelDefault = True
End Sub


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

Итак, по этой же схеме можно поймать все штатные команды меню Access'а. Осталось выяснить Id код для каждой команды. Для "Создать MDE-файл..." Id = 2073, для "Сжать и восстановить базу данных" Id = 2071. А для других команд какой Id?
Для этого запускаем вот такой код и узнаем Id:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Sub GetCommandBarControlID()
    Dim Ctrls   As CommandBarControls
    Dim Ctrl    As CommandBarControl
    Dim strCmnd As String
    
    strCmnd = InputBox("Введите фрагмент названия команды меню.", "Фрагмент")
    If Len(strCmnd) = 0 Then
        Exit Sub
    Else
        strCmnd = "*" & strCmnd & "*"
    End If
    
    Set Ctrls = CommandBars.FindControls(Type:=msoControlButton)
    For Each Ctrl In Ctrls
        If Ctrl.Caption Like strCmnd Then
            MsgBox Ctrl.Caption & "     Id = " & Ctrl.Id
        End If
    Next Ctrl
End Sub


Правда есть маленький нюанс: если в названии команды есть горячая клавиша (нижнее подчеркивание буквы), то перед этой буквы не забываем вставить & когда InputBox будет спрашивать фрагмент названия команды.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37742233
ALEXIS_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Покопался в своих архивах. нашел вот такую табличку по кодам меню. (см. прил. файл)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37744487
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ALEXIS_22,

Thank you very much!
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37746128
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чуть выше (а именно вот здесь 12324615 ) я написал, что свойство "ZoomControl" нельзя использовать внутри модуля отчёта. Ну нельзя так нельзя! Но если очень хочется, то можно. :) Правда не без танцев с бубнами. :)
Чисто из-за "спортивного интереса" решил всё-таки попробовать заставить работать "ZoomControl".
Если повесить код "Me.ZoomControl = 125" на событие "Report_Activate", то происходит следующее:
Когда мы отчёт открываем первый раз, то Access ругается. Но зато потом, когда отчёт теряет фокус и обратно получает фокус, то уже не ругается. Стало быть перед "Me.ZoomControl = 125" следует добавить "On Error Resume Next". Однако, мы не получим моментального результата - масштаба 125% при первом же открытии отчёта. Как же всё таки получить моментального такого эффекта?
Итак, в модуль базы (не в модуль отчёта, а в отдельный модуль) добавляем вот такой код:
Код: vbnet
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.
Public Declare Function SetTimer Lib "user32" ( _
          ByVal Hwnd As Long, _
          ByVal nIDEvent As Long, _
          ByVal uElapse As Long, _
          ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" ( _
          ByVal Hwnd As Long, _
          ByVal nIDEvent As Long) As Long


Sub StartTimer(RunProgram As String, MSec As Long)
    If Len(RunProgram) = 0 Or MSec <= 0 Then
        Exit Sub
    Else
        strProgram = RunProgram
    End If
    SetTimer Application.hWndAccessApp, 1, MSec, AddressOf TimerProc
End Sub

Private Sub TimerProc()
    KillTimer Application.hWndAccessApp, 1
    Eval strProgram
End Sub

Function ReportZoomControl(ReportName As String, Zoom As Integer) As Boolean
    On Error Resume Next
    ' По умолчанию масштаб 125.
    If Zoom = 0 Then Zoom = 125
    
    If Len(ReportName) = 0 Then
        ReportName = Screen.ActiveReport.Name
        If Len(ReportName) = 0 Then Exit Function
    End If
    
    Reports(ReportName).ZoomControl = Zoom
    ReportZoomControl = (Err.Number = 0)
End Function



Далее, в модуле отчёта пишем так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Private Sub Report_Activate()
    Static Opened As Boolean
    DoCmd.Maximize
    If Opened = False Then
        Opened = True
        StartTimer "ReportZoomControl('" & Me.Name & "', 125)", 100
    Else
        Me.ZoomControl = 125
    End If
End Sub


Для получения "почти" моментального эффекта я взял 0,1 секунд (красным отметил 100). Если у Вас "тяжёлый" отчёт, то возможно придётся "чуть-чуть" добавить.

P.S. В принципе если требуется запуск какой-либо процедуры, но при этом не дожидаясь завершить первоначальную процедуру, а потом спустя некоторое время продолжить работу второй процедуры, то можно использовать такую схему работы.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37749848
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как-то недавно пробегал топик, где шла речь о спец. форматах. Там ещё и база была приложена с примером. Если в текстовое поле (именно только текстовое!) указать формат ">[синий]" (или blue в английских версиях), то в режиме таблицы данное поле будет окрашено синим цветом (в хелпе есть перечень цветов: Black, Blue, Green, Cyan, Red, Magenta, Yellow, White).
Что интересно если написать без ">", то такого эффекта не будет. Правда если указать цвет вместе с ">", то будет побочный эффект: все буквы будут прописными. Соответственно можно заменить на "<", но тогда буквы строчные.
А чтобы таких "побочных" эффектов не было, то нужно указать либо "!", либо "@" вместо ">", либо даже так "><" (последний вариант ещё хоть как-то логичный :) ).
Почему так, почему именно эти символы я так и не понял. Может кто-нибудь знает причину?
Есть ли ещё "загадочные" форматы? Не условные форматы (с ними вроде нет "загадочности") и не "красный цвет для отрицательных чисел", а какой-нибудь не очевидный формат? :)

Странно, но ещё можно написать и так: !@[Синий][Красный]
Тогда получим красный цвет, т.е. цвет, указанный последним в "списке".
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37749911
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

Лови
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37750540
ALEXIS_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvk

Да это интересно. Только для числовых полей и полей с датами не получилось. Там другое выражение для задания формата?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37750559
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ALEXIS_22,

о чём речь? если поковыряться, то можно всё сделать; можно и на форуме кстати поискать, как раз с числами что-то видел
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37750571
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ALEXIS_22,

Я сам тоже не знаю. Вот поэтому и спросил. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37750680
ALEXIS_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren

Просто раскрасить поля в запросе это одно. Но практическая ценность будет намного выше если как-то задавать формат в зависимости от значения в поле. Пока не выходит. Через iif пробую.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37750816
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ALEXIS_22,

конкретно задачу кто-нибудь поставит?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37750936
ALEXIS_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvkALEXIS_22,
конкретно задачу кто-нибудь поставит?

Я вот что вспомнил. Вот так можно форматировать поля с разными типами данных:

Код: vbnet
1.
!\ [Красный] 

- текстовый,
Код: vbnet
1.
# ##0,00[Черный];(-# ##0,00)[Красный]

- числовой,
Код: vbnet
1.
dd.mm.yyyy[Синий] 

- дата \ время

Дело в том, как задать формат поля в зависимости от содержащегося в нем значения? Для числового поля черные-положительные, красные отрицательные. Это понятно. А вот допустим для текста вывести в одном поле в таблице или в запросе "Красный" - красным цветом, "Зеленый" - зеленым. Вот это как, я не знаю. И думаю возможно ли такое вообще
Иначе зачем майкрософту Format Condition например?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37751271
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ALEXIS_22Дело в том, как задать формат поля в зависимости от содержащегося в нем значения? Для числового поля черные-положительные, красные отрицательные. Это понятно. А вот допустим для текста вывести в одном поле в таблице или в запросе "Красный" - красным цветом, "Зеленый" - зеленым. Вот это как, я не знаю. И думаю возможно ли такое вообще
Иначе зачем майкрософту Format Condition например?
Ну так "условное форматирование" ещё никто не отменял. :)
В отчётах например есть событие "форматирование", там в зависимости от значения поля можно и цветами баловаться.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37751293
ALEXIS_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren
Да, в отчетах это без проблем.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37751363
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ALEXIS_22studieren

Просто раскрасить поля в запросе это одно. Но практическая ценность будет намного выше если как-то задавать формат в зависимости от значения в поле. Пока не выходит. Через iif пробую.

если разговор о ленточных формах - то нет проблем. расскрасить можно как угодно
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37752698
ALEXIS_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вадяесли разговор о ленточных формах - то нет проблем. расскрасить можно как угодно
Да мне обычного условного форматирования для ленточных форм хватало (как правило). Если не хватало то FlexGrid использовал.
Кажется видел где-то пример раскраски для ленточных форм без УФ. Там действительно ограничений 3 условий нет.

Возвращаясь к основной теме про форматирование полей в запросе\таблице. Совершенно недавно видел пример использования такого форматирования полей в запросе для создания "цветных" ListBox и ComboBox. Даже его скачал. Первый раз открыл - подивился оригинальности, далее отложил. В свете этой теме решил к нему вернуться. И как не старался более эти цветные поля увидеть не смог. Значения в полях списка, к которым были применены форматы просто не видны. Пробовал в ACSE 2003 (SP3).
Если кто-то из обитателей форума знает о каком примере идет речь поделитесь были ли у кого с ним какие-то проблемы с реализацией такого списка.

Весь комизм текущей ситуации заключается в том, что я сейчас не имею возможности этот пример приложить. Попробую немного позже в инете снова его взять. Тогда приложу.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37753191
ALEXIS_22,

12190877 ?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37753225
ALEXIS_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
13-й квартал ALEXIS_22,
12190877?

Ну да! Он самый. У меня на одном компе отработал, на двух других нет.
Сейчас сижу далеко. В инет урывками поглядываю. Офиса здесь нет, проверить еще раз не могу. Только у себя - завтра к вечеру.
Как говорит Осьменоги - "ыыы-ыы-ы"
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37771619
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот здесь есть старинный код, с помощью которого можно узнать список названия компьютеров, подключённых к указанному файлу базы данных.
Sub ShowUserRosterMultipleUsers()
Dim cn As New ADODB.Connection
Dim cn2 As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim i, j As Long

cn.Provider = "Microsoft.Jet.OLEDB.4.0"
cn.Open "Data Source=c:\Northwind.mdb"

cn2.Open "Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=c:\Northwind.mdb"

' The user roster is exposed as a provider-specific schema rowset
' in the Jet 4 OLE DB provider. You have to use a GUID to
' reference the schema, as provider-specific schemas are not
' listed in ADO's type library for schema rowsets

Set rs = cn.OpenSchema(adSchemaProviderSpecific, _
, "{947bb102-5d43-11d1-bdbf-00c04fb92675}")

'Output the list of all users in the current database.

Debug.Print rs.Fields(0).Name, "", rs.Fields(1).Name, _
"", rs.Fields(2).Name, rs.Fields(3).Name

While Not rs.EOF
Debug.Print rs.Fields(0), rs.Fields(1), _
rs.Fields(2), rs.Fields(3)
rs.MoveNext
Wend

End Sub

Даже при аварийном завершении видимо Access успевает "отметится" как вылетевший и поэтому в списке пользователей не выходит (что вообщем-то хорошо!). Но!!! Если всё-таки Access не успеет подать сигнал о завершении, к примеру если внезапно вырубить от электропитания или выдернуть сетевой шнур (что не сделаешь ради эксперимента ), то из списка всё-таки не будет уходить.
Я решил в конце вместо "Debug.Print" склеить в строковую переменную и выдать сообщение через MsgBox. Типа так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Dim strUsers As String
While Not rs.EOF
    strUsers = strUsers & rs.Fields(0) & "   " &  rs.Fields(1) & "   " & _
        rs.Fields(2) & "   " & rs.Fields(3) & vbCrLf
    rs.MoveNext
Wend
MsgBox strUsers


Вот тут к моему удивлению обнаружил, что получаю имя компьютера только 1-пользователя! И ничего более!
Начал экспериментировать и выяснять причину. Оказывается "rs.Fields(0)" здесь возвращает имя компьютера и сразу же за ним символ Chr(0) и далее ровно столько пробелов, чтобы в общей сложности должно получиться 32 символа. И у этого символа Chr(0) (так сказать vbNullChar) есть странная особенность:
все символы после Chr(0) при вызове MsgBox или InputBox пропадают.
Код: vbnet
1.
2.
3.
4.
5.
Dim S As String

S = "Test is " & Chr(0) & " test!"
MsgBox S
S = InputBox(S, S)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37792018
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Создал запрос, где в параметрах сразу назначаю значение с помощью DLookUp:
Код: sql
1.
2.
3.
PARAMETERS A Text ( 255 ) = DLOOKUP("Name", "MSysObjects");
SELECT TOP 1 A AS X
FROM MSysObjects;


Сохранил и дал название "Запрос1". Вот теперь в так называемых "статистических функциях по подмножеству" (таких как DCount, DLookUp и т.д.) не возможно использовать этот запрос.
Код: vbnet
1.
?DCount("*", "Запрос1")


!---------------------------
Microsoft Visual Basic
---------------------------
Run-time error '2001':

Предыдущая операция прервана пользователем.
---------------------------
ОК Справка
---------------------------

А если использовать этих функций не в параметрах, а в SELECT или WHERE, то такой ошибки не получаем:
Код: sql
1.
2.
3.
SELECT TOP 1 Name
FROM MSysObjects
WHERE DCount("*", "MSysObjects")>0;



Код: vbnet
1.
2.
?DLookup("Name", "Запрос1")
Tables
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822393
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все программисты MS Access (да и не только Access) всячески стараются не работать с таблицами или запросами напрямую, в смысле не дают прямой доступ пользователям к таблицам / запросам. Почему? Ответ очевиден, полное отсутствие программного контроля, т.е. отсутствие "событий".
Когда база разрастается, и там появляются множества таблиц справочников, то создавать отдельную форму на все таблицы (или запросы) порой нет времени (или просто лень).
Когда "вручную" открываем таблицу (или запрос), то действительно сталкиваемся полным отсутствием всяких событий, на которых реагирует программа. Но если открывать программно, то оказывается, хотя бы на время можно искусственно создавать событие!
Приведу такой пример: допустим, пользователь работает с какой-то формой и там есть некий код справочника. Появилась необходимость ввода нового кода справочника. Что он должен делать? Открыть таблицу справочников и добавить новую запись. Находясь в форме, он может дважды щёлкнуть поле для кода справочника и тут программа может открыть таблицу, причём параллельно создать некоторые события таблицы. Ну скажем "BeforeUpdate", "AfterUpdate", "OnClose" и т.д.
Делается это очень и очень просто.
Для эксперимента создаём процедуру, где открываем таблицу и создаём временные события для таблицы.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub OpenTableWithEvents()
     DoCmd.OpenTable "Table1"
     With Screen.ActiveDatasheet
          .BeforeUpdate = "=MsgBox(""BeforeUpdate"")"
          .AfterUpdate = " =MsgBox(""AfterUpdate"")"
          .OnMouseMove = "=MsgBox(""OnMouseMove"")"
          .MouseWheel = "=MsgBox(""MouseWheel"")"
          .OnClose = "=MsgBox(""OnClose"")"
     End With
End Sub


После закрытия таблицы, увы, все эти события исчезнут.
Разумеется, вместо "MsgBox" можно написать собственную функцию, да и вместо таблицы можно и запрос на выборку точно таким же образом открывать. Тогда и можно программно контролировать, словно работаем с табличной формой.

P.S. Я конечно же не рекламирую работу с таблицами и запросами напрямую. Я тоже сторонник закрытия доступа к рядовым пользователям. Но иногда если есть необходимость, то могу поступать именно таким образом, т.е. программно открыть, чтобы программно же и контролировать действия пользователя. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822466
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

табличную форму для справочника сделать -> 3 - 5 минут.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822567
Фотография Старый ворчун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvkstudieren,

табличную форму для справочника сделать -> 3 - 5 минут.
Не это главное.
Вы, наверное, в курсе, что в качестве SourceObject подчиненной формы можно использовать таблицу или запрос?
Это бывает очень удобно использовать. Из одной формы можно сделать множество справочников. Решение studieren позволяет создавать события для такой подчиненной формы. Это, по крайней мере, интересно. А для профессионала дополнительный инструмент.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822593
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Старый ворчун,

Старый ворчунчто в качестве SourceObject подчиненной формы можно использовать таблицу или запрос

я такой вариант не приемлю, мне он не нравится.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822619
Фотография Старый ворчун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvkСтарый ворчун,

Старый ворчунчто в качестве SourceObject подчиненной формы можно использовать таблицу или запрос

я такой вариант не приемлю, мне он не нравится.

Но вам же никто и ничего не навязывал, не так ли? Вы в праве делать базы так как вам нравится.
А studieren делится своими наблюдениями и открытиями с другими, что заслуживает только одобрения.

И вообще, кто тут старый ворчун? :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822626
Guest33
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvkСтарый ворчун,

Старый ворчунчто в качестве SourceObject подчиненной формы можно использовать таблицу или запрос

я такой вариант не приемлю, мне он не нравится.

Эта тема уже обсуждалась и тоже нашла яростных противников 12336735
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822632
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Старый ворчунalvkСтарый ворчун,

пропущено...


я такой вариант не приемлю, мне он не нравится.

Но вам же никто и ничего не навязывал, не так ли? Вы в праве делать базы так как вам нравится.
А studieren делится своими наблюдениями и открытиями с другими, что заслуживает только одобрения.

И вообще, кто тут старый ворчун? :)

Ага не навязывал: "Вы наверное в курсе ... это удобно использовать..." (c)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822635
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Guest33alvkСтарый ворчун,

пропущено...


я такой вариант не приемлю, мне он не нравится.

Эта тема уже обсуждалась и тоже нашла яростных противников 12336735

"обсуждалось" - сильно сказано, скорее не удосужилась обсуждения .
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822644
Guest33
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvk"обсуждалось" - сильно сказано, скорее не удосужилась обсуждения.
Ну, приведите доводы против кроме:
я такой вариант не приемлю, мне он не нравится.
(довод за - уже был: одна фома на все справочники)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822646
Фотография Старый ворчун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvkАга не навязывал: "Вы наверное в курсе ... это удобно использовать..." (c)
Зачем вы занимаетесь подтасовкой? Несолидно.
Я не вижу навязывания в своих словах. Тем более никакого навязывания не было в топике studieren.
Но что-то заставило вас поворчать на его публикацию.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37822663
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Guest33alvk"обсуждалось" - сильно сказано, скорее не удосужилась обсуждения.
Ну, приведите доводы против кроме:
я такой вариант не приемлю, мне он не нравится.
(довод за - уже был: одна фома на все справочники)

это уже лучше делать в отдельном топике


Старый ворчунНо что-то заставило вас поворчать на его публикацию.

вообще-то высказать свою точку зрения.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37823615
alvk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Guest33alvk"обсуждалось" - сильно сказано, скорее не удосужилась обсуждения.
Ну, приведите доводы против кроме:
я такой вариант не приемлю, мне он не нравится.
(довод за - уже был: одна фома на все справочники)

кушайте не обляпайтесь
http://www.sql.ru/forum/actualthread.aspx?tid=945915
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37823669
Фотография Старый ворчун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alvkкушайте не обляпайтесь
http://www.sql.ru/forum/actualthread.aspx?tid=945915
это не проблема, ничто не мешает сохранять ширину столбцов и восстанавливать их при открытии.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37890751
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я раньше (до того, как узнал о форуме sql.ru) не знал, что в окне отладки можно получить значение любой функции поставив перед ней просто вопросительный знак.
Код: vbnet
1.
2.
? Date()
24.07.2012 


Не давно прочёл в одной книге, что не только вопросительный знак, ну и следующие варианты дают аналогичный эффект.
Код: vbnet
1.
2.
3.
4.
5.
6.
Debug.Print Date()
24.07.2012 
Debug.? Date()
24.07.2012 
Print Date()
24.07.2012 


Ну конечно "?" самый короткий, а значит самый "оптимальный". :-)

Ну не это меня больше всего удивило. Казалось бы какой сюрприз может дать простое "окно отладки"? Оказывается (а это действительно для меня было неожиданностью) в окне отладки можно поменять значение любой переменной во время исполнения процедуры. Т.е. я имею ввиду вот что!
Допустим, у нас есть вот такая процедура:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Sub Test()
    Dim i As Byte

    i = 10
    MsgBox i
    Debug.Assert False    ' или просто Stop
    ' Вот здесь когда процедура временно прервано и целая _
    ' строка отмечена жёлтым цветом в окне отладки набираем _
    ' i = 20    и нажимаем на Enter. Потом просто нажимаем F5 _
    ' т.е. продолжаем работу процедуры.
    MsgBox i
    ' После этого MsgBox даст нам 20, а не 10!
End Sub


Во время тестирования процедуры, когда нажимая на F8 пошагово проверяем тот или иной код этот трюк может оказаться очень даже полезным.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37891445
пехто
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren, ты описываешь использование окна отладки в контексте "подменить значение объявленной переменной". того же эффекта можно добиваться в окнах locals и watches.
Окно же отладки может чуть-чуть больше


просто набери в окне отладки (вне контекста исполнения какой-либо процедуры и без всяких знаков вопроса)

z = 20
MsgBox z

на офисном форуме есть люди, которые используют окно отладки просто для написания программ. Т.е. пишут в этом окне текст так, как писали бы его в "процедуре",
тут же просматривая результат выполнения.
Вроде того - открыл форму (лист excel и т.д.) и пишешь нужный код обработки, тут же, непосредственно глазками наблюдая - что именно делает твой код с формой/листом/итп
по мере написания кода, кажой его строки в отдельности.

Получив результат, копи-пастом помещаешь его в процедуру и , по вкусу, добавляешь объявления переменных.
немало больших любителей как-то так с офисом обходиться.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37891536
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пехтоstudieren, ты описываешь использование окна отладки в контексте "подменить значение объявленной переменной". того же эффекта можно добиваться в окнах locals и watches .
Спасибо.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37898158
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как известно, в формах Access'а можно создать "виртуальную" RecordSet как с помощью DAO, так и ADO. В файлах mdb / accdb по умолчанию применяется DAO. Так если в RecordSource формы укажем название таблицы или запроса в таких базах, то Access применяет технологию DAO. Но в принципе и в таких базах можно применить ADO Recordset и при этом не потерять обновляемость записей.

Что это даёт?
1). Любую форму созданную в mdb / accdb файлах можно импортировать в adp и наоборот, при этом Access будет работать одинаково нормально и там, и там!
2). В adp файлах также появиться возможность достучаться к любой базе минуя linked server, а не только к SQL Server. Главное – был бы соответствующий доступ!
3). Есть такие типы данных в SQL Server как: numeric(n, m), decimal(n, m), bigint, date, money. Если в таблице SQL Server использованы эти типы данных, то после "обычной" линковки, то в файлах mdb / accdb будут проблемы с обновлением данных. Т.е. если в форме укажем в качестве RecordSource название линкованной таблицы, то уже либо невозможно внести изменение в таблице, либо саму таблицу / форму вообще невозможно даже открыть. Ну а если в RecordSource формы подсучить ADO Recordset, то как не странно таких проблем вообще не будет!
4). Если у Вас стоит Office ниже 2010, ну а SQL Server 2005 и выше, есть такая особенность: если создать схему данных отличной от "dbo" и назначить владельцем (а точнее "передать защищаемых сущностей между схемами") этой таблицы указать данную схему, то в файле adp невозможно даже открыть таблицу и соответственно связанную форму.
Пример:
Создаём схему на стороне SQL Server
Код: sql
1.
2.
3.
4.
CREATE SCHEMA Test;
GO
ALTER SCHEMA Test TRANSFER dbo.tblTest;
GO


После этого таблицу "Test.tblTest" в adp файле невозможно открыть.
Ну а если к форме подсучить ADO Recordset, то как не странно можно и открыть, и править данные без проблем.
5). Можно вообще удалить все линкованные таблицы и все запросы в mdb / accdb файлах, а adp файл сделать "неподключаемым", т.е. сделать его как бы "без таблиц и запросов", но при открытии формы сразу подключаться к любой базе. Иначе говоря, полностью убрать доступ к таблицам и запросам у пользователей.

Итак, как для этого нужно с помощью ADO подключаться?
Для получения обновляемой таблицы Access в форме применяем вот такой код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Dim Con As ADODB.Connection
Dim RS  As ADODB.Recordset
Dim strCnn As String

Set Con = New ADODB.Connection
Con.ConnectionString = "Provider=Microsoft.Access.OLEDB.10.0;" & _
    "Persist Security Info=False;" & _
    "Data Source=Здесь указываем полное название файла;" & _
    "User ID=Admin;" & _
    "Data Provider=Microsoft.Jet.OLEDB.4.0"
Con.Open
Set RS = New ADODB.Recordset
RS.Open "Здесь название таблицы", Con, adOpenKeyset, adLockOptimistic
Set Me.Recordset = RS

Set RS = Nothing
Set Con = Nothing



А для получения обновляемой таблицы SQL Server применяем этот же код, но только, разумеется, с другой строкой подключения.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Dim Con As ADODB.Connection
Dim RS  As ADODB.Recordset
Dim strCnn As String

Set Con = New ADODB.Connection
Con.ConnectionString = "Provider=Microsoft.Access.OLEDB.10.0;" & _
    "Persist Security Info=False;" & _
    "Data Source=Здесь название сервера;" & _
    "User ID=Здесь Login пользователя;" & _
    "Password=123456;" & _
    "Initial Catalog=Название базы;" & _
    "Data Provider=SQLOLEDB.1""
Con.Open
Set RS = New ADODB.Recordset
RS.Open "Здесь название таблицы желательно с указанием схемы", Con, adOpenKeyset, adLockOptimistic
Set Me.Recordset = RS

Set RS = Nothing
Set Con = Nothing


P.S. Есть очень интересная статья "AccessConnection и связанные с ним новые возможности форм mdb" по данной теме. Идея взята из данной статьи.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37921602
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как снять бекап базы данных в SQL Server, при чём достаточно снять копию файла ".mdf" и ".ldf"? Т.е. сложный бекап, где можно откатить базу по состоянию на n-дату не требуется.

Для решение этой задачи необходимо временно выключить SQL Server "по хорошему". :)
В первую очередь я решил получить список Win. служб с помощью WMI и посмотреть там как "обзывается" SQL Server. :)
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
Sub ListOfServices(Optional CompName As String)
    Dim Services As Object, Service As Object
    Dim strSQL   As String
    
    If Len(CompName) = 0 Then
        CompName = InputBox("Введите имя компьютера", "Остановка служб", ".")
        If Len(CompName) = 0 Then Exit Sub
    End If
    
    strSQL = "SELECT * FROM Win32_Service"
    Set Services = GetObject("winmgmts:\\" & CompName & "\root\cimv2").ExecQuery(strSQL)
    For Each Service In Services
        Debug.Print Service.Name
    Next
    
    Set Service = Nothing
    Set Services = Nothing
End Sub


Здесь "Win32_Service" имеет следующие "поля".
Название поля Тип данныхAcceptPause booleanAcceptStop booleanCaption stringCheckPoint uint32CreationClassName stringDescription stringDesktopInteract booleanDisplayName stringErrorControl stringExitCode uint32InstallDate datetimeName stringPathName stringProcessId uint32ServiceSpecificExitCode uint32ServiceType stringStarted booleanStartMode stringStartName stringState stringStatus stringSystemCreationClassName stringSystemName stringTagId uint32WaitHint uint32

К примеру, чтобы сократить "записи" возвращаемого запроса, можно применить и такой запрос:
Код: sql
1.
SELECT * FROM Win32_Service WHERE Name LIKE '%SQL%'



Потом создал VBA функцию, которая включает/выключает любую указанную службу.
Код: vbnet
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 StartOrStopService(ServiceName As String, _
        ToStart As Boolean, Optional CompName As String) As String
    Dim Services  As Object, Service As Object
    Dim strSQL    As String
    Dim Result    As Long
    Dim strResult As String
    
    If Len(CompName) = 0 Then
        CompName = InputBox("Введите имя или IP адрес компьютера", _
            "Наименование или IP адрес компьютера", ".")
        If Len(CompName) = 0 Then Exit Function
    End If
    
    If Len(ServiceName) = 0 Then
        ServiceName = InputBox("Введите имя службы", "Наименование службы")
        If Len(ServiceName) = 0 Then Exit Function
    End If
    
    strSQL = "SELECT * FROM Win32_Service WHERE Name = '" & ServiceName & "'"
    Set Services = GetObject("winmgmts:\\" & CompName & "\root\cimv2").ExecQuery(strSQL)
    For Each Service In Services
        If ToStart = True Then
            Result = Service.StartService()
        Else
            Result = Service.StopService()
        End If
        Select Case Result
        Case 0: strResult = "Success"
        Case 1: strResult = "Not Supported"
        Case 2: strResult = "Access Denied"
        Case 3: strResult = "Dependent Services Running"
        Case 4: strResult = "Invalid Service Control"
        Case 5: strResult = "Service Cannot Accept Control"
        Case 6: strResult = "Service Not Active"
        Case 7: strResult = "Service Request Timeout"
        Case 8: strResult = "Unknown Failure"
        Case 9: strResult = "Path Not Found"
        Case 10: strResult = IIf(ToStart, "Service Already Running", "Service Already Stopped")
        Case 11: strResult = "Service Database Locked"
        Case 12: strResult = "Service Dependency Deleted"
        Case 13: strResult = "Service Dependency Failure"
        Case 14: strResult = "Service Disabled"
        Case 15: strResult = "Service Logon Failure"
        Case 16: strResult = "Service Marked For Deletion"
        Case 17: strResult = "Service No Thread"
        Case 18: strResult = "Status Circular Dependency"
        Case 19: strResult = "Status Duplicate Name"
        Case 20: strResult = "Status Invalid Name"
        Case 21: strResult = "Status Invalid Parameter"
        Case 22: strResult = "Status Invalid Service Account"
        Case 23: strResult = "Status Service Exists"
        Case 24: strResult = "Service Already Paused"
        End Select
    Next Service
    
    Set Service = Nothing
    Set Services = Nothing
    
    StartOrStopService = strResult
End Function


Здесь параметр функции "ToStart" если имеет значение True, то включает службу, а если False, то наоборот выключает.

Ну и потом создал VBA процедуру, которая сначала выключает службу " MSSQL$MSSQLSERVER2008 " (здесь у меня "MSSQLSERVER2008" это название инстанса). Затем копирует нужные файлы ".mdf" и ".ldf" на резервную папку и в конце обратно включает SQL Server.

P.S. Разумеется чтобы провернуть всё это необходимо иметь права администратора.

P.S.S. А нет ли решение ещё более "продвинутое"?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37921614
qwerty112
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenКак снять бекап базы данных в SQL Server, при чём достаточно снять копию файла ".mdf" и ".ldf"?
я, вот, не понял смысл бекапирования файлов БД ...

почему не бекап, в смысле BACKUP DATABASE ?
сервер останавливать - не надо, с правами - проще (backupoperator),
нуу, и хранение, файлом, файла лога, который может быть "ни-себе-чего-размером", тоже не айс ...

зы
по WMI, конечно интересно
вот, в тему, думаю будет интересно - http://www.msadmin.ru/index.php?option=com_content&view=article&id=8:scripts4&catid=4:scripts&Itemid=5
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37921658
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwerty112я, вот, не понял смысл бекапирования файлов БД ...

почему не бекап, в смысле BACKUP DATABASE ?
сервер останавливать - не надо, с правами - проще (backupoperator)
Почему то у меня после "штатного" BACKUP DATABASE размер файла "mdf" растёт неимоверно. Я так понимаю, сервер видимо внутри файла хранит "точку возврата" после каждого бекапа. В смысле возможность восстановление базы по состоянию на n-дату. А в тех базах, о которых я тут написал, как только снимаю копию, предыдущая версия на проч теряет смысл, она просто из-за ненадобности перестает быть полезной.
Ну если Вы знаете секрет "тупого" бекапа (как в моём случае), после которого база не растёт из-за бекапа, please подскажите. Я не селен в SQL Server.

P.S. А за ссылку WMI спс. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37921667
?????
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: sql
1.
BACKUP DATABASE [BaseName] TO  DISK = N'C:\Archiv\BaseName.dat' WITH  INIT ,  NOUNLOAD ,  NAME = N'BaseName backup',  NOSKIP ,  STATS = 10,  NOFORMAT 
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37921672
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
?????,

За скрипт спасибо. Попробую на работе.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37921801
Фотография Программист-Любитель
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прочитайте в bol про модели восстановления. У мсскл сервера возможности бекапирования перекрывают ваши хотелки - научитесь ими пользоваться. Вы изобретаете велосипед с квадратными колесами.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37924404
Bryk_Alien
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сделал в одной форме кнопко для просмотра адреса:
Почемучто Яндех не хочет кушать русскую букву "Я", я придумал менять её на "Z", умный Яндех кушает и правильно находит...

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
'Открытие яндекс-карты
Private Sub btnMap_Click()
    Dim sSearch As String
On Error GoTo ErrorHandler
    sSearch = Nz(Me.txtQryCity, "") & " " & Nz(Me.txtQryAddress, "")
    sSearch = Replace(sSearch, "я", "z")
    Call Shell("c:\Program Files\Internet Explorer\iexplore.exe http://maps.yandex.ru/?text=" & sSearch, vbMaximizedFocus)
ExitHere:
    Exit Sub
ErrorHandler:
    MsgBox Err.Source & "-->" & Err & ":" & Err.Description, vbExclamation, "Error"
    Resume ExitHere
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37931516
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы узнать существование файла иногда используют вот такой код:
Код: vbnet
1.
Len(Dir("C:\Test.txt"))


Dir имеет ряд недостатков. Вот здесь 1415057 и постом ниже пишут как раз о недостатках Dir. Я случайно обнаружил ещё 1 недостаток. Если файл "скрытый", т.е. свойство "Hidden" = True, то Dir на отрез его не видит. :-)
Поэтому сам использую простой код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Function IsFileExists(FileName As String) As Boolean
    Dim FSO As Object   ' Scripting.FileSystemObject
    
    Set FSO = CreateObject("Scripting.FileSystemObject")
    IsFileExists = FSO.FileExists(FileName)
    Set FSO = Nothing
End Function


Другой вариант предлагает Старый Ворчун: Как проверить сущесвование фала?
Вообще то у VBA есть разные функции помимо FileLen (к примеру FileDateTime), но что странно эти функции (кроме GetAttr) почему то не "различают" папку от файла. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37931554
Фотография Старый ворчун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenЯ случайно обнаружил ещё 1 недостаток. Если файл "скрытый", т.е. свойство "Hidden" = True, то Dir на отрез его не видит. :-)в функции dir можно указать attributes
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37931691
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Старый ворчун,

Да, точно. Прозевал 2-параметр функции.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37937232
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Когда в проекте имеется битая ссылка (reference), то такие функции как Left, Right, Mid перестают работать (FAQ: А почему у меня не работает... Q1). Я заметил и такую закономерность:
Если перед Left, Right, Mid поставить " VBA. ", т.е. так
Код: vbnet
1.
VBA.Left, VBA.Right, VBA.Mid

то даже при битом референсе программа уже не ругается.


P.S.
Для одного проекта (когда программа 1-раз устанавливается у юзера) как раз это "фишка" помогла мне.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37943119
Bryk_Alien
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если зайти в
---> Панель управления –> Администрирование –> Источники данных
и попытаться настроить пользовательский ODBC, то винда выдаст ошибку 196. Это происходит потому, что вызывается настройщик для 32х разрядной системы.

Для того чтобы вызвать настройщик для 64-х битной винды нужно найти файл:
%WINDIR%\SysWOW64\odbccad32.exe
и запустить его.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37946925
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenЧтобы узнать существование файла иногда используют вот такой код:
Код: vbnet
1.
Len(Dir("C:\Test.txt"))


...
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Function IsFileExists(FileName As String) As Boolean
    Dim FSO As Object   ' Scripting.FileSystemObject
    
    Set FSO = CreateObject("Scripting.FileSystemObject")
    IsFileExists = FSO.FileExists(FileName)
    Set FSO = Nothing
End Function


Другой вариант предлагает Старый Ворчун: Как проверить сущесвование фала?
Есть ещё 1 "штатный", но только слегка скрытый способ:
Код: vbnet
1.
2.
3.
4.
Function IsFileExists(FileName As String) As Boolean
    On Error Resume Next
    IsFileExists = Application.WizHook.FileExists.FileExists(FileName)
End Function


Тут "On Error Resume Next" нужен на всякий случай, типа "сеть недоступен" и т.д., и т.п.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37946930
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ой, очепятка. :)
Код: vbnet
1.
2.
3.
4.
Function IsFileExists(FileName As String) As Boolean
    On Error Resume Next
    IsFileExists = Application.WizHook.FileExists(FileName)
End Function
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37947670
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я тут слегка опять ошибся, не добавил "магический ключ" для "WizHook".
Код: vbnet
1.
2.
3.
4.
5.
Function IsFileExists(FileName As String) As Boolean
    On Error Resume Next
    Application.WizHook.Key = 51488399
    IsFileExists = Application.WizHook.FileExists(FileName)
End Function


Провел такой эксперимент: от самого минимального (-2147483648) до самого максимального (2147483647) целого числа типа long программно перебрал все значения для ключа "WizHook". Только и только в случае 51488399 WizHook работает нормально.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37960202
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я как-то на лесенке (вот здесь 13162105 ) задал вопрос "как программно поменять папку в окне диалога". В смысле программно подменить папку таким образом, чтобы при нажатии Ctrl+O оказаться в нужной папке. Но при этом опцию "Default Database Directory" не трогать, чтобы другие базы не пострадали.
Проблему мог бы решить и простой код ChDir, который по описанию хелпа как раз таки должен был изменить текущую папку. Но проблема в том, что ChDir совсем не влияет на Ctrl+O.
Решение оказывается всё-таки существует. Вот и сам код, которого я в тот момент искал:
Код: vbnet
1.
CreateObject("WScript.Shell").CurrentDirectory="C:\"


Свойство "CurrentDirectory" оказывается не только для чтения, но и для записи.
Оно как раз таки влияет на Ctrl+O.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37998637
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А2003.
Наткнулся чисто случайно на такую вещь.
Если поменять свойство базы данных "ANSI Query Mode" на True (оказывается такое свойство по умолчанию существует для mdb файлов),
Код: vbnet
1.
CurrentDB.Properties("ANSI Query Mode") = True

то в "Сервис" ==> "Параметры" во вкладке "Синтаксис для SQL Server (ANSI 92)" появляется птичка там, где "текущая база данных".
После этого попробовал вот такой код:
Код: vbnet
1.
2.
?DCount("*", "MSysObjects", "name like '%'")
0

Как видно из результата пока что ANSI 92 "не вступил в силу". :)
По идее если стоит галка SQL Server (ANSI 92), то вместо "*" должен работать "%".
Когда программно меняю свойство "ANSI Query Mode", то такой номер поначалу не проходит. Но как только перезагружаю БД, то проходит. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #37998647
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
studierenТолько и только в случае 51488399 WizHook работает нормально.
735770
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38007740
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такой dll файл, который находится по умолчанию вот здесь "C:\WINDOWS\system32\FM20.DLL". Когда его подключаем к проекту VBA, то появляется референс "Microsoft Forms 2.0 Object Library". По названию понятно, что работает с формами VBA (но не формами MS Access).
Есть полезная особенность этой библиотеки: помимо прочего работает с буфером обмена (clipboard). Может прочесть из буфера (метод GetFromClipboard) или наоборот скопировать в буфер (PutInClipboard). Вот примерчик из help'a:
GetFromClipboard
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
Dim MyData as DataObject

Private Sub CommandButton1_Click()
    'Need to select text before copying it to Clipboard
    TextBox1.SelStart = 0
    TextBox1.SelLength = TextBox1.TextLength
    TextBox1.Copy

    MyData.GetFromClipboard
    TextBox2.Text = MyData.GetText(1)
End Sub

Private Sub UserForm_Initialize()
    Set MyData = New DataObject
    TextBox1.Text = "Move this data to the " _
        & "Clipboard, to a DataObject, then to "
        & "TextBox2!"
End Sub 


PutInClipboard
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Dim MyData As DataObject

Private Sub CommandButton1_Click()
    Set MyData = New DataObject
    
    MyData.SetText TextBox1.Text
    MyData.PutInClipboard

    TextBox2.Paste
End Sub

Private Sub UserForm_Initialize()
    TextBox1.Text = "Move this data to a " _
        & "DataObject, to the Clipboard, then to " _
        & "TextBox2!"
End Sub


Решил найти способ позднего подключения к этой библиотеке, чтобы не быть зависимым от версии офиса / ОС и т.д. Нашёл только 1 способ:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub PutInClipboardSomeText(SomeText As String)
    If Len(SomeText) > 0 Then
        Dim MyData As Object
        Set MyData = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        
        MyData.SetText SomeText
        MyData.PutInClipboard
        Set MyData = Nothing
    End If
End Sub


Вместо таинственного "заклинания" new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69} другую более понятную "формулировку" не нашёл. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38007792
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: vbnet
1.
2.
Dim objdata As MSForms.DataObject
Set objdata = New MSForms.DataObject



http://www.cpearson.com/excel/Clipboard.aspx
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38007802
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сорри. я недопонял/не прочитал текст.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38008139
Фотография Панург
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВместо таинственного "заклинания" new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69} другую более понятную "формулировку" не нашёл. :)
А нет другой формулировки. Посмотрел в "OLE/COM Object Viewer"
Может свой класс? У Гетца есть.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38009030
ЦЦа
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenРешил найти способ позднего подключения к этой библиотеке, чтобы не быть зависимым от версии офиса / ОС и т.д. Нашёл только 1 способ:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub PutInClipboardSomeText(SomeText As String)
    If Len(SomeText) > 0 Then
        Dim MyData As Object
        Set MyData = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        
        MyData.SetText SomeText
        MyData.PutInClipboard
        Set MyData = Nothing
    End If
End Sub

Вместо таинственного "заклинания" new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69} другую более понятную "формулировку" не нашёл. :)Нет ProgID у MSForms.DataObject. Желающие могут добавить в реестр
пару строк
Код: plaintext
1.
2.
3.
4.
5.
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\MSForms.DataObject]

[HKEY_CLASSES_ROOT\MSForms.DataObject\CLSID]
@="{1C3B4210-F441-11CE-B9EA-00AA006B1A69}"
и создавать объект через CreateObject("MSForms.DataObject"), но смысл при его весьма ограниченной в плане поддержки форматов функциональности ускользает.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38010897
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЦЦаНет ProgID у MSForms.DataObject. Желающие могут добавить в реестр+
пару строк
Код: plaintext
1.
2.
3.
4.
5.
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\MSForms.DataObject]

[HKEY_CLASSES_ROOT\MSForms.DataObject\CLSID]
@="{1C3B4210-F441-11CE-B9EA-00AA006B1A69}"
и создавать объект через CreateObject("MSForms.DataObject"), но смысл при его весьма ограниченной в плане поддержки форматов функциональности ускользает.
Я так понимаю теоретически можно создать любую ветку в Win регистре да хоть "Чёрт знает что" по аналогию, ну а потом в VBA создавать CreateObject("Чёрт знает что")!
Забавно!!! Но что самое главное работает!!! :)

ЦЦа,
Большое СПАСИБО за наводку!
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38010994
Фотография Панург
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

А какой смысл создавать ProgId если его нет?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38010999
Фотография Панург
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

Если нужен объект, то можно создать его и через CLSID, что успешно проделывается в твоём коде. А если нет класса, то в любом случае не поможет.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38011096
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Панургstudieren,

А какой смысл создавать ProgId если его нет?
Да по приколу можно в своем проекте везде создавать объект CreateObject("Хрень") и работать с ним. Если кто-нибудь и скопирует саму базу, то там (в других компах) конечно всё это не будет работать.

P.S. Это так сказать из той оперы что-то вроде "пригвоздить проект на основе серийного номера харда". :)
P.S.S. Я не сторонник радикальной защиты файла БД, а просто можно оказывается и так защитить кое-что в своей базе. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38012496
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bryk_AlienЕсли зайти в
---> Панель управления –> Администрирование –> Источники данных
и попытаться настроить пользовательский ODBC, то винда выдаст ошибку 196. Это происходит потому, что вызывается настройщик для 32х разрядной системы.

Для того чтобы вызвать настройщик для 64-х битной винды нужно найти файл:
%WINDIR%\SysWOW64\odbccad32.exe
и запустить его.
Случайно наткнулся на блог Как настроить MS Access ODBC драйвер на windows7 x64 или vista x64
Там как раз об этом идёт речь.
Текст блогаОднажды возникла проблема при установке одной программы, та программа требовала настроить ODBC драйвер (microsoft access driver) на windows 7. При входе в "Источники данных (ODBC)" можно было только добавить драйвер SQL Server'а. Требуемого драйвера не было. Я перерыл множество инструкций и форумов прежде чем нашел совет, который мне помог. Вот он "How to Use Microsoft Access ODBC drivers for Vista x64/ Windows 7 x64".

Оказывается в Vista/Windows7 x64 есть две копии odbcad32.exe, один из них находится в "C:\Windows\syswow64\ ", а другой в "C:\Windows\system32\". Открывая как обычно "Источники данных (ODBC)" через "панель управления — администрирование", мы открываем второй вариант odbcad32.exe, то есть тот, который располагается в "C:\Windows\system32\" и у нас нет нужного нам драйвера ODBC!

Необходимо открыть вот этот файл "C:\Windows\syswow64\odbcad32.exe". Там без особых проблем можно установить MS Access ODBC driver.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021364
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Создал обычный текстовый файл "V.vbs" и написал внутри простой код:
Код: vbnet
1.
Msgbox Format(Date(), "mm.dd.yyyy")


Когда запускаю, то программа ругается.
Error: Type mismatch: 'Format'
Code: 800A000D
Source: Microsoft VBScript runtime error
Как же так?

Попробовал вот такой код в VBA, который вызывает VBScript:
Код: vbnet
1.
2.
3.
4.
5.
Dim O As Object
Set O = CreateObject("ScriptControl")
O.Language = "VBScript"
O.AddCode "Msgbox Format(Date(), ""mm.dd.yyyy"")"
Set O = Nothing


И опять программа ругается: Type mismatch: 'Format'
Это что же получается? Банальная функция Format в VB скриптах работает как-то не так?
Может как-то "по особому" надо "объяснить" ему как нужно работать с датой?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021408
ЦЦа
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021414
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЦЦа,

Я так понимаю у VBScript нет такой функции Format???
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021427
Фотография ILL HEAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

msgbox другой
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021432
Фотография ILL HEAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ILL HEADstudieren,

msgbox другойтам где Формат написал - там кнопки прописываются. а Формата кажысь нет.
тебе влом скачать ВБСу хелп с тырнета?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021443
ЦЦа
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,

Format-ов в VBS не один на все случаи, а 4:
FormatCurrency
FormatDateTime
FormatNumber
FormatPercent
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021471
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЦЦа,

Мне вообще-то нужно было дату превратить в 'yyyymmdd', чтобы отправить запрос к SQL Server. Поэтому решил использовать Format, но как-то не подумал (и не проверил), что у VBScript нету такой функции. :)
Это я по инерции пользователя VBA. :-)
Ну нет, значит нет. Буду использовать самопальную функцию.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38021488
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ILL HEADstudieren,

msgbox другой
VBScript умеет работать с Msgbox. Можете проверить. :)

ILL HEADтебе влом скачать ВБСу хелп с тырнета?
Да не влом. У меня вот здесь C:\Program Files\Microsoft Office\OFFICE11\1049\VBSCRIP5.CHM "по умолчанию" уже был хелп, видимо когда устанавливал офис там в дистрибутиве уже был.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38022449
Фотография ILL HEAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

сильно извиняюсь. поразил приступ косоглазия.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043350
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если нужно заменить 2 и более подряд идущие пробелы на 1 пробел, то можно воспользоваться Replace скажем так:
Код: vbnet
1.
strText = Replace(strText, "  ", " ")


Но что делать если подряд идут 4 или 5 пробелов, а по условиям задачи требуется, чтобы между слов оставался не более одного пробела? Ведь после замены в таком случае все равно останутся 2 и более пробелов.
Когда-то в таких случаях я пользовался циклом: продолжал до тех пор пока длина строки переставала сокращаться. Но после изучения регулярных выражений понял, что есть более изящное решение. :)
А код такой:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Public Function ReplaceDoubleSpaces(strText As String) As String
    Static objRegExp As Object
    
    Set objRegExp = CreateObject("VBScript.RegExp")
    objRegExp.Global = True
    objRegExp.Pattern = " {2,}"
    ReplaceDoubleSpaces = objRegExp.Replace(strText, " ")
    Set objRegExp = Nothing
End Function


В принципе вместо пробела (там где отмечено красным цветом) можно использовать и другой символ или даже группа символов. Отличие от простейшего Replace заключается в том, что за 1 раз заменяются все 2 и более пробела на 1, в связи с чем вовсе не требуется цикла.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043427
Фотография qwrqwr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenНо что делать если подряд идут 4 или 5 пробелов, а по условиям задачи требуется, чтобы между слов оставался не более одного пробела? Ведь после замены в таком случае все равно останутся 2 и более пробелов.
Регулярки - это хорошо и универсально, но хочу вставить 5 копеек в защиту риплейса. :)
N вложенных риплейсов заменяют на один пробелы, количеством не более, чем (2^N).
То есть, если мы уверены, что имеем не более 16-ти пробелов подряд - нам гарантировано хватает 4 риплейсов:
Код: vbnet
1.
2.
?Replace(Replace(Replace(Replace("test                test", "  ", " "), "  ", " "), "  ", " "), "  ", " ")
test test
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043436
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,

проверил на досуге .... тож вариант

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Public Function strspace(strtext As String)
strspace = ""
a = Split(strtext, " ")
For i = LBound(a) To UBound(a)
If a(i) <> "" Then strspace = strspace & a(i) & " "
Next i
End Function
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043439
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwrqwr... N вложенных риплейсов заменяют на один пробелы, количеством не более , чем (2^N).
...
Мне удалось (с разбегу) заменить 38 пробелов 4 риплейсами.
Подозреваю, это не предел. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043457
!??
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
!??
Гость
nord-woolfqwrqwr... N вложенных риплейсов заменяют на один пробелы, количеством не более , чем (2^N).
...
Мне удалось (с разбегу) заменить 38 пробелов 4 риплейсами.
Подозреваю, это не предел. :)
Если пройти подобный инстанс, состоящий, к примеру, из 808 пробелов, то их останется ещё больше
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043483
Фотография nord-woolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
от 808 пробелов осталось всего 6.
:)
Код: vbnet
1.
2.
?Replace(Replace(Replace(Replace("test" & Space(808) & "test", Space(7), Space(1)), Space(4), Space(1)), Space(3), Space(1)), Space(2), Space(1))
test      test


"Рабочий" диапазон до 40 пробелов подряд.
Потом врет.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043490
!??
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
!??
Гость
nord-woolf,

а Автор сказал 16
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043645
Фотография qwrqwr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
!??nord-woolf,
а Автор сказал 16

Зонуды, блин.
Вообще-то всегда можно уложиться и в три риплейса.
Код: vbnet
1.
2.
? Replace(Replace(Replace("test" & Space(100500) & "test", " ", " "&chr(0)), chr(0)&" ", ""), " "&chr(0), " ")
test test
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043675
Фотография Сергей Лалов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот еще интересный факт, свойство таблицы, замеченное в ms access 2007. Называется "Отслеживание строк." Попробуйте активировать данное свойство, не работает. Это рудимент для сервера?:
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38043852
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwrqwrВообще-то всегда можно уложиться и в три риплейса.
Код: vbnet
1.
2.
? Replace(Replace(Replace("test" & Space(100500) & "test", " ", " "&chr(0)), chr(0)&" ", ""), " "&chr(0), " ")
test test



Чрезвычайно оригинальное решение.

А как заставить в REPLACE работать постановочных знаков (wildcard)? Вообще такое возможно?
Сам я думаю, что нет. Но глядя на то, как здесь лихо справляются с трудными задачами, думаю у знатоков может есть "секретные" приёмы?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38046086
!??
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
!??
Гость
studieren,
Код: vbnet
1.
    Static objRegExp As Object


Судя по тому, что буквально не "по хэлпам", то Статик здесь осмысленно? Для чего?
Спасибо
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38046329
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
!??,

Ой, ошибочка вышла. Я эту функцию использовал для одного запроса и там в конце у меня не было "Set objRegExp = Nothing". Я вот в конце обнулить переменного не забыл, но зато в начале забыл заменить "Static" на "Dim". :)
Конечно же функция должна выглядеть так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Public Function ReplaceDoubleSpaces(strText As String) As String
    Dim objRegExp As Object
    
    Set objRegExp = CreateObject("VBScript.RegExp")
    objRegExp.Global = True
    objRegExp.Pattern = " {2,}"
    ReplaceDoubleSpaces = objRegExp.Replace(strText, " ")
    Set objRegExp = Nothing
End Function


Спасибо за поправку.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38046365
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если хотите использовать эту же функцию в запросах, то функция должна выглядеть так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Public Function ReplaceDoubleSpaces(strText As String) As String
    Static objRegExp As Object
    If objRegExp Is Nothing Then
        Set objRegExp = CreateObject("VBScript.RegExp")
        objRegExp.Global = True
        objRegExp.Pattern = " {2,}"
    End If
    ReplaceDoubleSpaces = objRegExp.Replace(strText, " ")
End Function


Но честно говоря всё-таки идея qwrqwr намного лучше, ибо там вообще не требуется использование какого-либо объекта. Более того, при таком раскладе функция получается более универсальной как для самой VBA, так и для запросов.
Код: vbnet
1.
2.
3.
4.
Public Function ReplaceDoubleSpaces(strText As String) As String
    ReplaceDoubleSpaces = Replace(Replace(Replace(strText, " ", " " & Chr(0)), _
        Chr(0) & " ", ""), " " & Chr(0), " ")
End Function


Да и прямо в самом запросе можно 3 Replace'а подсучить.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38048311
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обнаружил одну странность Access'а (2003).
Запускаю вот такой запрос
Код: sql
1.
SELECT @Version AS V


Здесь "@Version" как бы неявно объявленный параметр. Как и подобает в таких случаях Access спрашивает значение параметра, что в общем-то логично. Но как только стоит мне объявить (как "хороший" мальчик), то здесь происходит чудеса.
Код: sql
1.
2.
PARAMETERS @Version Text(255);
SELECT @Version AS V


Теперь Access НЕ спрашивает значение, а сразу показывает свою версию.
Я понимаю, что использовать ключевые слова не есть хорошо, но почему в первом варианте он не показывает версию Access'а? Вот тут не совсем понятно.
И вообще, какие зарезервированные слова ведут себя подобным образом?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38048347
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кажется начал понимать в чём тут дело. ИМХО все свойства объекта "Application" имеют такую особенность.
Код: sql
1.
2.
PROCEDURE @Build Long, BrokenReference Bit, [CurrentObjectName] Text(255);
SELECT @Build, BrokenReference, [CurrentObjectName]


Забавно! :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38048348
qwerty112
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
нда, интересно... :)
studieren...
И вообще, какие зарезервированные слова ведут себя подобным образом?
похоже, любые проперти Access.Application так можно "достать"

Код: sql
1.
2.
PARAMETERS @Visible bit, @UserControl bit; 
select @Visible, @UserControl


@Visible@UserControl-1-1
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38048358
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwerty112,

Ну надо же, первый раз обогнал qwerty112 по нажатию кнопок.
Тока написал, а он тут как тут. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38048373
qwerty112
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwerty112похоже, любые проперти Access.Application так можно "достать"

но "работает" или в сохр.запросах, или через Application.DoCmd
что в общем-то и "ожидалось" ...

Код: vbnet
1.
DoCmd.RunSQL "PARAMETERS @Version Text(255); update Q set qqq=@version"
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38059793
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В Excel'е есть очень полезная штука "QueryTable", с помощью которой можно импортировать данные из любой СУБД. Создаём запрос к серверу и получаем данные.
Вот что делать если запрос с параметром?
Раньше я в программе динамически создавал запрос и в свойство CommandText подменял текст запроса каждый раз. Вчера как-то решил по приколу поменять примерно вот такого рода текст для СУБД SQL Server:
Код: sql
1.
SELECT * FROM dbo.Table1 WHERE ID = ?


Решил попробовать обновить запрос "вручную" и очень удивился, когда Excel не вернул ошибку, а стал спрашивать значение параметра!
Мне и в голову не приходило, что можно в Excel'е соорудить запрос с параметром, да так, чтобы у юзера программа сама стала бы спрашивать значения и при этом без единого кода. Соответственно я и не искал в help'е и где-нибудь в и-нете что-либо подобное. А тут такое! :)
Короче, эксперименты показали, что вместо константное значение для параметра можно просто проставлять вопросительные знаки и каждый знак Excel понимает как очередной параметр.
Код: sql
1.
EXEC MyStorProc @Parameter1 = ?, @Parameter2 = ?


Можно оказывается программно вставить более предметную подсказку типа "Введите код клиента". Например так:
Код: vbnet
1.
2.
ActiveSheet.QueryTables(1).Parameters(1).SetParam _
     xlPrompt, "Введите код клиента"


Более того можно сделать ссылку на определённую ячейку, чтобы Excel не спрашивал значение параметра, а сразу брал значение с указанной ячейки. Для этого вместо значения нужно написать что-то вроде "=Лист1!A1" и вуаля!
Ну и много, много чего можно ещё нарыть в help'е. :)

P.S. Ну извиняйте ежли баян! :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38059798
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня офис 2003. Там выходит вот такое диалоговое окно.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38059806
!??
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
!??
Гость
studierenУ меня офис 2003. Там выходит вот такое диалоговое окно.
studieren,
похоже, когда-то стоял 2007, а это, судя по датапикеру, какие-то обломки от него остались
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38059818
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
!??studierenУ меня офис 2003. Там выходит вот такое диалоговое окно.
studieren,
похоже, когда-то стоял 2007, а это, судя по датапикеру, какие-то обломки от него остались
Вроде никогда не устанавливал офис 2007. Разве что в виртуалку. Ну это окно я получил с "боевого коня", а там строго 2003. Сейчас у соседей попробую.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38059829
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
!??studierenУ меня офис 2003. Там выходит вот такое диалоговое окно.
studieren,
похоже, когда-то стоял 2007, а это, судя по датапикеру, какие-то обломки от него остались
Только что проверил у соседей, у которых отродясь НИКОГДА не был установлен офис 2007 вообще. Точь в точь такое же диалоговое окно. Так что на обломки не похоже. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38059860
Фотография qwrqwr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВот что делать если запрос с параметром? тут было
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38066199
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем известно, что если скопировать текст из окна редактора VBA и при этом если язык клавиатуры не "русский", то кириллица после вставки текста превращается в крякозябру.
Как-то тестировал кусочек кода в Excel'е (там в отличии от Access открываем новую книгу и не сохранив сам файл можем сразу тестировать код). Не посмотрев на язык клавиатуры скопировал в базу и сохранил, а Excel файл разумеется не сохранил. :)
Там название некоторых объектов, комментарии и тексты Msgbox, в общем все превратилось в неудобочитаемый текст. :)
Раньше не знал о существовании такого простого трюка. Оказывается весь этот текст можно скопировать в Word и там "Сервис" ==> "Исправить поврежденный текст" и вуаля! Весь текст опять "нормальный"!

Ну и это не всё!
Прилагаю файл "CodePage.reg", которого нужно просто запустить и согласиться с тем, чтобы некоторые Win реестры изменились.
текст файлаWindows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]
"1250"="c_1251.nls"
"1251"="c_1251.nls"
"1252"="c_1251.nls"
"1253"="c_1251.nls"
"1254"="c_1251.nls"
"1255"="c_1251.nls"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange]
"Unicode"="E000-F8FF"

После этого обязательно нужно перезагрузить Windows. Если у Вас Win XP, то теперь смело можете копировать и вставить тексты из VBA и наоборот, и при этом совсем можно игнорировать раскладку клавиатуры. "Крякозябры" не появятся.

P.S. У меня в ноутбуке Win 7. Увы, там этот номер почему-то не проходит.
Кто-нибудь знает как заставить Win 7 работать так как надо со шрифтами / Unicode и прочие, прочие, прочие ???
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38066201
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блин сам файл не сцепился с первого разу.
Исправляю. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38066305
адв
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenБлин сам файл не сцепился с первого разу.
Исправляю. :)А ведь и вправду - юбилей ( клац )

10 лет - круглая дата
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38066395
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
адв,

Честно говоря я не знал (собственно и не искал), что в форуме уже были темы о реестре "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]".

Ну если Вы всё знаете может подскажите что нужно исправить в Win 7, чтобы и там можно было копировать любой текст из VBA?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38066416
адв
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,

под вин7 не работаю, только тестирую.
Не подскажу, к сожалению, ибо не сталкивался с проблемой.

зы. А где я писал, что всё знаю? ;)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38103507
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть у контролов (textbox, combobox) форм свойство "KeyboardLanguage" (Язык клавиатуры). Если поставить там "English", то при получении фокуса данным контролом язык клавиатуры сразу переходит на английский. Штука очень полезная, но вот беда! Совсем не работает в табличной форме. Выкрутился так:
В свойство "OnGotFocus" (Получение фокуса) написал:
Код: vbnet
1.
=SysCmd(710;67699721)


Здесь 67699721 так сказать "InputLocaleID" для английского языка, если верить вот этой статье .
Ну а для русского языка - 68748313.
Допустим мы не знаем этот код для других языков. Как же узнать?
Всё очень и очень просто. Сначала вручную сами переводим язык клавиатура на нужный язык и после этого в окне отладки пишем так:
Код: vbnet
1.
2.
?SysCmd(711)
 68748313 


После чего и получим нужный код "InputLocaleID".

P.S.
А в табличных формах есть ли другой способ перевода языка клавиатуры? Только вот Win API не самое лучшее решение, т.к. в зависимости от 32- или 64-разрядной ОС код может сработать, а может и нет.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38103527
ZezaM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren..., т.к. в зависимости от 32- или 64-разрядной ОС код может сработать, а может и нет.
дико сорю
нам посчатливилось досталось -- 'безвременье'

рицепт -
- ждать....)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38161855
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как-то я уже спрашивал вот здесь 11371576 вопрос, который звучит примерно так:
Если у формы источником записей служит таблица, линкованная через ODBC в SQL Server, то как можно поймать текст сообщения об ошибке именно сервера?

P.S. Версия: А2003, формат: mdb.

Нашёл по теме вот такую статью ACC2000: Cannot Trap Specific ODBC Errors on OnOpen Property of a Form
Там как раз таки написано о причине данной проблемы:
ODBC error messages normally consist of two components. The first component is error 3146, whose description is:
ODBC--Call failed
The server-specific error information is contained in the second component, from which you can retrieve an error number and a description such as:
[Microsoft][ODBC SQL Server Driver][SQL Server] <Server-specific error message> (#<error number>)

Ну и совсем слегка переделал тот код и у меня получился следующее:
Код: vbnet
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.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
Public Function SaveRecODBC(Frm As Form) As Boolean
    Dim Ctrl As Access.Control
    Dim Fld  As DAO.Field
    Dim E    As DAO.Error
    
    On Error GoTo ODBC_Error
    With Frm.RecordsetClone
    If Frm.Dirty = True Then
        If Frm.NewRecord = True Then
            .AddNew
            For Each Ctrl In Frm.Controls
                Select Case Ctrl.ControlType
                Case acTextBox, acComboBox, acListBox, acCheckBox
                    Select Case Left$(Ctrl.Properties("ControlSource").Value & "=", 1)
                    Case "="
                    Case Else
                        If IsNull(Ctrl.Value) = False Then
                            For Each Fld In .Fields
                                If Fld.Name = Ctrl.Properties("ControlSource").Value Then
                                    Fld.Value = Ctrl.Value
                                    Exit For
                                End If
                            Next Fld
                        End If
                    End Select
                End Select
            Next Ctrl
            .Update
        Else
            .Bookmark = Frm.Bookmark
            .Edit

            For Each Ctrl In Frm.Controls
                Select Case Ctrl.ControlType
                Case acTextBox, acComboBox, acListBox, acCheckBox
                    Select Case Left$(Ctrl.Properties("ControlSource").Value & "=", 1)
                    Case "="
                    Case Else
                        For Each Fld In .Fields
                            If Fld.Name = Ctrl.Properties("ControlSource").Value Then
                                If Fld.Value <> Ctrl.Value Or _
                                        IsNull(Fld.Value) <> IsNull(Ctrl.Value) Then
                                    Fld.Value = Ctrl.Value
                                End If
                                Exit For
                            End If
                        Next Fld
                    End Select
                End Select
            Next Ctrl
            .Update
        End If ' End If Frm.NewRecord
    End If ' End If Frm.Dirty
    End With
    SaveRecODBC = True

Exit_SaveRecODBCErr:
    Set Ctrl = Nothing
    Set Fld = Nothing
    Set E = Nothing
    Exit Function

ODBC_Error:
    Dim strTxt As String
    Dim strErr As String
    
    For Each E In DBEngine.Errors
        strTxt = E.Description
        If strTxt Like "*[[]SQL Server[]]*" Then
            strTxt = Mid$(strTxt, InStr(1, strTxt, "[SQL Server]") + 12)
            If strTxt Like "*([#]*" Then
                strTxt = Left$(strTxt, InStr(1, strTxt, "(#") - 1)
            End If
            ' Если уже имеется как минимум 1 текст ошибки на русском языке, то текст ошибки _
              на английском можно пропустить.
            If Len(strErr) = 0 Or E.Description Like "*[А-я]*" Then
                strErr = strErr & vbCrLf & strTxt
            End If
        End If
    Next E
    MsgBox Mid$(strErr, 3)
    SaveRecODBC = False
    Resume Exit_SaveRecODBCErr
End Function

Function BeforeUpdateOfForm(Optional Frm As Access.Form) As Integer
    If Frm Is Nothing Then Set Frm = Screen.ActiveForm
    
    ' Попробуем сохранить изменения.
    If SaveRecODBC(Frm) = True Then
        Frm.Undo
        ' Если текущая запись новая, то следует переходить на последную запись.
        If Frm.NewRecord = True Then
            DoCmd.GoToRecord acForm, Frm.Name, acLast
        End If
        BeforeUpdateOfForm = 0
    Else
        ' Елси не удалось сохранить изменения, то следует вернуть -1 для отмены _
          обновления.
        BeforeUpdateOfForm = -1
    End If
End Function

...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38161862
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Весь код, который я "спрятал" под спойлер нужно держать в отдельном модуле.
Ну а в форме на событие BeforeUpdate пишем так:
Код: vbnet
1.
2.
3.
Private Sub Form_BeforeUpdate(Cancel As Integer)
    BeforeUpdateOfForm Me
End Sub

или в свойство "До обновления" пишем так:
=BeforeUpdateOfForm([Form])

Вопрос:
А нет ли каких-либо подвох в этом коде? Ну я имею ввиду нет ли там косяков и не будет ли где-то поджидать "сюрприз"?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38246569
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересный факт я обнаружил. Если мы переменную величину объявляем как Integer, Date и т.д., то переменная ведёт себя также соответственно как Integer, Date и т.д., но некоим образом не как Variant. По идее всё так. Но! Бывает оказывается и исключение! :)
Если в модуле объявляем переменную как Private или через Dim, то тут происходит нечто необычное.
Код: vbnet
1.
2.
Private I As Integer
Dim D As Date


Теперь если в окне отладки просто запустить вот такой код, то MsgBox как не странно будет пустым.
Код: vbnet
1.
2.
MsgBox I
MsgBox D


Если же проверить их на IsEmpty, то тут выясняется что IsEmpty(I) = True.
Вот если этих же переменных объявить как Public, то уже MsgBox не пустой.

Что это даёт в таком случае?
Бывает иногда полезным узнать программным путём "использована" ли переменная (т.е. задавали ли мы хоть какое-либо значение). Если тип Variant, то достаточно было просто проверить IsEmpty, а вот с другими типами IsEmpty всегда возвращал False. Оказывается бывает и исключение. :)

P.S. Сильно извиняюсь если баян. Из-за лени не стал искать в нашем форуме или в гугле, а сразу здесь же опубликовал. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38246577
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Странно! Если я в окне отладки пытаюсь передать строковую значению, то почему-то у меня VBA не ругается.
Код: vbnet
1.
I = "Test"


Как так? Значит если мы объявляем переменную как Private или Dim, то уже не имеет значение какой у него тип, всё равно будет как Varinant?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38246587
йййй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Даже если у вас в модуле написано "option explicit", то для окна "immediate" это свойство не установлено. Возможно, что только по умолчанию, и где-то можно переключить, не важно.

Так вот, если переменная на момент попытки её использования еще ни разу не была использована (читай, инициализирована), то создаётся новая переменная уровня окна immediate с типом variant. Со всеми вытекающими.

В общем-то, предсказуемое поведение
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38246588
ййййй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Т.е. если переменные выше уровнем не удалось найти в памяти, то происходит примерно следующее:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Option Compare Database
Option Explicit

Public b As Integer
Dim c As Long

Sub Immediate()
  Static b As Variant
  Static c As Variant
  
  b = "123"
  c = "abc"
End Sub
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38246606
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ййййй,

Упппс! Привык куски своих кодов проверять в окне отладки. Как-то не подумал, что окно отладки не видит эти переменные. :)
Случайно "наткнулся" при проверке очередного своего кода и не разобрался. Первом делом подумал, что это такая особенность VBA. :)
Реально sorry! :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38247068
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Создал нижеследующий простейший код (Property) в MS Access и в MS Excel / Word:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Option Explicit
Dim varResult As Variant

Public Property Get Result() As Variant
    Result = varResult
End Property

Public Property Let Result(ByVal varValue As Variant)
    varResult = varValue
End Property


Если запускаю вот такой код в окне отладки MS Access, то ошибки не возникает и программа возвращает значение, а вот в Excel / Word ругается:
Код: vbnet
1.
2.
Result=10:  Run("Result")
 10


Run по разному работает в разных продуктах офиса?

P.S.
Мне нужно было передать значение какой-либо переменной БД, находясь извне (т.е. в чужой среде) и потом в MS Access прочесть это значение. Конечно можно просто сохранить это значение в какой-либо таблице и в MS Access прочесть это. Но хотелось бы избежать создание лишних таблиц. Во время эксперимента и выяснил, что Run по разному работает в разных офисных продуктах.
В связи с чем ещё 1 вопрос: как народ поступает в таких случаях?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38505385
Bryk_Alien
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Условное форматирование Access 2010

Условное форматирование в акцесс 2003 было ограничено тремя вариантами

Как вы, наверное, уже знаете, в 2010 акцессе это ограничение было убрано (причём, довольно коряво). Это выражается в том, что через удобный интерфейс можно добавить хоть 100500 вариантов условного форматирования для поля. Лично я, когда проверял, остановился на 25 вариантах... Но, если вы попытаетесь считать или добавить условные форматирования посредством VBA, вам будут доступны только первые три варианта. Попытка обратиться к остальным вызовет ошибку.

Ковыряясь во внутренностях контрола, в наборе Properties я обнаружил 2 свойства:
№ 128 - ConditionFormat
№ 129 - ConditionFormat14

Оба эти Properties-а имеют формат битового поля. Только в первом случае свойство хранит информацию о первых трёх уровнях форматирования, а во втором случае - массив данных о всех условных форматированиях, которые можно присвоить контролу.

Для набора из пяти свойств, данные могут выглядеть так:
Массив данных в Hex
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
01 00 05 00 00 00 01 00 00 00 00 00 00 00 01 00 
00 00 FF 00 00 00 FF FF FF 00 0C 00 00 00 5B 00 
74 00 78 00 74 00 43 00 6F 00 6C 00 6F 00 72 00 
5D 00 3D 00 31 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 
00 00 00 01 00 00 00 FF C2 0E 00 FF FF FF 00 0C 
00 00 00 5B 00 74 00 78 00 74 00 43 00 6F 00 6C 
00 6F 00 72 00 5D 00 3D 00 32 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
01 00 00 00 00 00 00 00 01 00 00 00 FF F2 00 00 
FF FF FF 00 0C 00 00 00 5B 00 74 00 78 00 74 00 
43 00 6F 00 6C 00 6F 00 72 00 5D 00 3D 00 33 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 
00 22 B1 4C 00 FF FF FF 00 0C 00 00 00 5B 00 74 
00 78 00 74 00 43 00 6F 00 6C 00 6F 00 72 00 5D 
00 3D 00 34 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 
00 00 01 00 00 00 00 B7 EF 00 FF FF FF 00 0C 00 
00 00 5B 00 74 00 78 00 74 00 43 00 6F 00 6C 00 
6F 00 72 00 5D 00 3D 00 35 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Код хранит пять условных форматирований с разными цветами текста для условий [txtColor]=1 ... [txtColor]=5

Если этот массив данных присвоить какому-нибудь элементу в соответствующее свойство, то этот элемент станет обладать соответствующим набором условных форматирований. Так же можно передавать набор форматирований от одного контрола - другому:
Код: vbnet
1.
Me.txt2.Properties(129) = Me.txt1.Properties("ConditionFormat14")



Может, кому пригодится...
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38505396
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Bryk_Alien Условное форматирование Access 2010
Это бы в Недокументированные фичи http://www.sql.ru/forum/47491 и в Баги http://www.sql.ru/forum/85650 ...
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38534511
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть топик Саныча «Узнать программно, послан ли отчет на принтер или на предпросмотр?» . Там есть решение, суть которого – повесить на событие Format заголовка отчёта примерно вот такой код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Private Sub ReportHeader_Format(Cancel As Integer, FormatCount As Integer)
    On Error Resume Next
    DoCmd.OpenReport Me.Name, acViewPreview
    If Err.Number <> 0 Then
        ' Отчёт отправлен на печать. Вот здесь и отмечаем в нужной таблице о данном факте.
    End If
End Sub



Когда отравляем на печать отчёта «DoCmd.OpenReport» вызывает ошибку. Как это работает не совсем понятно. Всё бы ничего, но только у меня возникла проблема. Есть у меня одна база данных, где «DoCmd.OpenReport» не возвращает ошибку, даже если с режима предварительного просмотра отчёт отправляем на печать. Вроде бы файл не испорчен, попробовал импортировать в новую базу, да и попробовал удалить все модули и воссоздать заново их (у Joss есть специальная программка, которая так и делает). Короче ничего не помогло, после чего попробовал пойти другим путём.
На печать мы можем отправить двумя способами:
1) сначала открыв отчёт в режиме предварительного просмотра и затем нажимая на Ctrl+P.
2) сразу отправляем на печать.
Код: vbnet
1.
DoCmd.OpenReport "Название отчёта", acViewNormal


Случай № 1. Если открываем отчёт в режиме предварительного просмотра, то в заголовке отчёта 1 раз происходит событие «Format» и если отправляем этот же отчёт на печать, то и данное событие совершается уже 2-раз. Стало быть, если установим глобальный счётчик внутри модуля отчёта или какую-нибудь метку, то при совершении повторного события будем знать, что отчёт отправлен на печать. Причём, даже если отчёт отправлен на печать не полностью, а только некоторые страницы (не обязательно начиная с первой стр.), то всё равно повторно происходит событие «ReportHeader_Format». Итак, повторное совершение события «ReportHeader_Format» информирует нас об отправке на печать отчёта.
Случай № 2. При открытии отчёта в режиме предварительного просмотра совершается событие «Activate», а при отправке на печать без предварительного просмотра это событие не происходит вовсе. В общем-то, логично! Стало быть, на момент «Activate» ставим метку о том, что отчёт активирован и на момент закрытия отчёта «Close» смотрим, не был ли отчёт активирован. Если отчёт был активирован, то ничего не делаем внутри события «Close». А если всё таки активации не произошло, то тогда смотрим, не был ли заголовок отчёта отформатирован хотя бы раз. Если не был, то это означает, что отчёт не открыт вовсе (ну например, из-за отсутствия данных после фильтра). А если был, то отчёт отправлен на печать без предварительного просмотра.
Вот и код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Private Sub ReportHeader_Format(Cancel As Integer, FormatCount As Integer)
    With ReportHeader
        If Len(.Tag) = 0 Then
            .Tag = "ReportHeader_Format"
        Else
            ' Отчёт отправлен на печать. Вот здесь и отмечаем в нужной таблице о данном факте.
            MsgBox "Отчёт отправлен на печать после предварительного просмотра!", vbInformation
        End If
    End With
End Sub

Private Sub Report_Activate()
    Report.Tag = "Report_Activate"
End Sub

Private Sub Report_Close()
    If Report.Tag <> "Report_Activate" Then
        If ReportHeader.Tag = "ReportHeader_Format" Then
            ' Отчёт отправлен на печать. Вот здесь и отмечаем в нужной таблице о данном факте.
            MsgBox "Отчёт отправлен на печать без предварительного просмотра!", vbInformation
        End If
    End If
End Sub



P.S. А не прозевал ли я какую-нибудь подвоху? В смысле бывают ли случаи, когда этот код не работает? У кого какие мысли?
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38534678
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,

капельку подправил ваш код, а то событие срабатывало даже в момент предпросмотра (на радость всё работает даже при "поднятии" экземпляра класса отчета :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38535360
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,

А вот так уже не работает :(
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38535759
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,

поправил, теперь и в последнем случае всё нормально отрабатывает (да, всёж ФАК иногда перечитывать надо .... )))))) чешу "репу"))))
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38545110
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если подключить в референсах VBA " C:\WINDOWS\system32\scrrun.dll " (у меня Win XP, в других версиях возможно месторасположение файла чуть-чуть другое), то в списке библиотек появится " Microsoft Scripting Runtime ". Теперь нажимаю F2 и в " Object Browser " выбираю библиотеку " Scripting ". Выбираю из списка любую интересующую меня функцию и нажимаю F1, чтобы прочесть справочный материал. Всё время у меня выходило пустое окно.
Есть один замечательный топик "Программно получить список классов и всех членов этого класса из библиотеки в References" , где есть код, с помощью которого можно получить много интересных свойств библиотек. Например, " MetodHelp ". Так вот, попробовал я и этот файл " C:\WINDOWS\system32\scrrun.dll " анализировать, так у него оказывается свойство " MetodHelp " = " C:\WINDOWS\system32\VBENLR98.CHM ". Смотрю я в свой компьютер и не нахожу этот файл. Поэтому и у меня пустое окно. Нашёл в и-нете вот здесь этот файл и поместил в папку " C:\WINDOWS\system32 ". Пустое окно исчезло, то вместо него компьютер начал ругаться. Как я понял из "ругани" компа, видимо этот файл был изначально предназначен для Windows 98, а у меня Windows XP. В инете нашёл вот такой топик Associate a help file with a library in the VBA object brower . Как я понял из данного топика файл был переименован " VBLR6.CHM " и находится совсем в другом месте (в моём случае вот здесь " C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\1033\VBLR6.CHM "). Скопировал я этот файл и разместил копию в папке " C:\WINDOWS\system32 ", да и переименовал как " VBENLR98.CHM ".
И О ЧУДО!!!!!
Программа совершенно перестала ругаться и самое главное начала открывать нужный справочный материал.

P.S.
Сколько же библиотек якобы "без справочного материала"? Microsoft видимо много раз переименовал и переместил в разные папки, да так, что приходится искать очень долго, чтобы найти.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38545170
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вывод:
Если вместо справочного материала получаем пустое окно, то предварительно с помощью нижеуказанной функции узнаём полное название и местоположение справочного файла.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Function GetMetodHelp(FileName As String) As String
    Dim objTypeLib As Object
    Set objTypeLib = CreateObject("TLI.TypeLibInfo")
    objTypeLib.ContainingFile = FileName
    GetMetodHelp = objTypeLib.HelpFile
    Set objTypeLib = Nothing
End Function


P.S. Чтобы функция заработала, разумеется, нужно заранее зарегистрировать файл tlbinf32.dll .

После этого ищем этот файл в нужной папке. Если нет его там, то находим и размещаем туда. :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38715665
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дано: А2003, Win XP.

Есть такой тип данных "date" в SQL Server (если не ошибаюсь начиная с версией 2005 появился этот тип данных). Когда линкую таблицу, то Access воспринимает этот тип как текст, а не дата. Причина как оказывается в драйвере. Если использовать драйвер "SQL Server", то так и происходит. Ну а если использовать более "свежий" драйвер "SQL Server Native Client 10.0", вот там "date" как дата. Ну и другие типы данных вроде бы читаются без проблем. (Недавно был топик, где об этом и было написано).
Вот только одна проблема. Если тип данных "varchar( Max )", то этот драйвер теперь совсем "плохо читает" (почему-то не показывает первые 255 символов). Сталкивался ли кто-либо с такой проблемой? Может в строке подключения что-то надо "подкрутить"?
Экспериментирую с различными строками подключения, пока безрезультатно.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823258
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,
получить строку значений столбца запроса (сконкатенировать столбец) можно , подключив библиотеку Excel и использовав функцию Transpose из этой библиотеки , тогда эту операцию можно записать одной строкой
Код: vbnet
1.
2.
?join(excel.Application.WorksheetFunction.Transpose(excel.Application.WorksheetFunction.Transpose(currentdb.OpenRecordset("select фамилия from сотрудники").GetRows(currentdb.OpenRecordset("select count(фамилия) from сотрудники")(0)))),",")
Белова,Новиков,Бабкин,Воронов,Кротов,Акбаев,Кралев,Крылова,Ясенева
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823332
\\\\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
guest_rusimport, очень спорное решение. Гораздо проще получить строку через ADO (GetString), ИМХО.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823452
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
\\\\guest_rusimport, очень спорное решение. Гораздо проще получить строку через ADO (GetString), ИМХО.
не понял , а спорить то тут о чем ? :) есть такой вариант , и он работает :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823541
\\\\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
guest_rusimport...не понял , а спорить то тут о чем ? ...Это не спор, это (см. название топика) анализ чужих решений... ;-)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823846
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
\\\\,
ну, тогда уж надо было указать достоинства , недостатки, сравнить с другими вариантами :)
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
интересные факты / наблюдения / анализ чужих и собственных решений
    #39927121
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для решения одной специфической задачи мне пришлось группировать записи и умножить значения, а не просуммировать. Дело в том, что существует агрегатная функция суммирования (SUM), а вот умножения (Multiply) – нет. Как быть?
Есть несколько способов решения данной задачи.

Вариант №1.
Нужно в VBA функции динамически создать SQL текст запроса (перебирая циклом) и перед запуском самого запроса подменить текст. Что-то вроде этого:
Код: sql
1.
2.
3.
4.
SELECT * FROM
(SELECT 1 AS ID, 2*115*17 AS RESULT FROM MSysObjects WHERE ID = 2
UNION ALL SELECT 2 AS ID, 19*13 AS RESULT FROM MSysObjects WHERE ID = 2
UNION ALL SELECT 3 AS ID, 24*10*15*7 AS RESULT FROM MSysObjects WHERE ID = 2) AS Data


Данный метод хорош, когда речь идёт о сравнительно небольшом количестве записей. Если же речь идёт о сотни тысяч, а то и более записей, то этот метод не годится. Во-первых, слишком долго будет программа обрабатывать циклом записи и во-вторых, SQL текст запроса не бесконечный, миллион символов не переварит.

Вариант №2.
Создаём VBA функцию, которая циклом перебирает значения по указанному ID и умножает значения. А в тексте запроса просто указываем название VBA функции. Метод хорош, но для большого количества записей будет требовать много времени на обработку.

Вариант №3.
Создаём VBA функцию, которая также циклом перебирает значения по указанному ID и превратив числовое значение в текстовое будет сцеплять их. Что-то вроде «2*115*17» для каждого ID. А в тексте запроса указываем название VBA функции, при этом обернув полученное значение дополнительной функцией EVAL. Этот метод хуже, чем вариант №2. Кроме того, из-за режима «печосницы» (SandboxMode) функция EVAL может и не работать у всех.

Вариант №4.
На просторах интернета я встретил самую необычную и изящную идею. Тот, кто додумался до этого, просто гений! Я бы сам никогда не додумался. Метод настолько очаровал меня, что я решил поделиться им. Оказывается агрегатной функции SUM вполне достаточно! Но вот только придётся изощряться. Дело в том, что сумма логарифмов с одинаковым основанием равняется как раз таки логарифму точно с таким основанием, но с умножением значений. Т.е.:
LN(A1) + LN(A2) + … + LN(An) = LN(A1*A2*…*An)
Чтобы избавиться от логарифма полученное таким образом значение потом нужно будет воздвигать в степень e.
Правда тут есть нюансы: все умножаемые числа должны быть больше 0, а для этого придётся брать только абсолютное значение и параллельно ввести учёт знаков. Ну и в случае нулевого значения добавить «костыль».
И так. Чтобы было более понятно о чём речь создаём таблицу в VBA и добавляем тестовые значения.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Sub Test()
  CurrentDb.Execute "CREATE TABLE Test (ID Long, Val Double)"
  CurrentDb.Execute "INSERT INTO Test (ID, Val)" & vbCrLf & _
    "SELECT * FROM" & vbCrLf & _
    "(SELECT 1 AS ID, 2 AS Val FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 1, 115 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 1, -17 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 2, 19 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 2, 13 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 24 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 10 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 15 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 7 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 4, 0 FROM MSysObjects WHERE ID = 2) AS Data"
End Sub


Вот теперь и запускаем вот такой запрос:
Код: sql
1.
2.
3.
4.
SELECT ID, EXP(SUM(LOG(ABS(IIf(Val=0, 1, Val))))) * (-1)^(SUM(IIf(Val<0,1,0))) * MIN(IIf(Val=0, 0, 1)) AS Mulltiply
FROM Test
GROUP BY ID
ORDER BY 1;


Выражение « (-1)^(SUM(IIf(Val<0,1,0))) » необходимо чтобы следить за знаком (в случае если окажется отрицательное число).
Выражение « MIN(IIf(Val=0, 0, 1)) » необходимо для выяснения нет ли 0 среди умножаемых значений.
Как то так.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #39927123
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если Вы точно знаете, что среди значений нет нуля и все числа всегда положительные, то и текст запроса будет проще.
Код: sql
1.
2.
3.
4.
SELECT ID, EXP(SUM(LOG(Val))) AS Mulltiply
FROM Test
GROUP BY ID
ORDER BY 1;



P.S.
Конечно же нужно учесть при этом, что если умножаемых чисел слишком много или же сами числа достаточно огромные, то может возникнуть ошибка переполнения.
...
Рейтинг: 0 / 0
280 сообщений из 280, показаны все 12 страниц
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / интересные факты / наблюдения / анализ чужих и собственных решений
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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