Рассылка статей | Программирование и готовые решения
Leadersoft.ru

Рассылка статей

Программирование и готовые решения

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

Выпуск 93. Нарушение авторских прав в Интернете

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

 

Перепечатка статей из Интернета. Законны ли эти действия?


    Ярким примером в Интернете, кто копирует информацию с сайтов, а потом выдает ее как свою собственную является
Компания Интерфейс (далее Интерфейс), сайт interface_ru. Для того, чтобы перейти на этот сайт, замените _[подчеркивание] на [.]точку. Это сделано для того, чтобы эта ссылка не индексировалась поисковыми машинами, и тем самым не поднимался рейтинг сайта. Об этом будет сказано чуть позже. Собственная точка зрения Интерфейса на публикацию данных:

Мы ...только перепубликовали на другом сайте с ссылкой на оригинальный источник (на ваш сайт). В-вторых, в законодательстве Российской Федерации нет законов, которые регламентируют публикацию материалов в Интернете. Единственное упоминание о данной теме в законе об авторском праве. Но там, правда, есть пометка, что необходимо указывать оригинальный источник, мы его указали.

А вот мои 7 выводов на эти действия.

   Вывод 1. Очевидно, что информацию Интерфейс копирует не для того, чтобы внести вклад в развитие науки и Интернета, а как можно быстрее раскрутить свой сайт при минимальных затратах. Понятно, что для написания статей по базам данных нужно нанимать специалистов, платить им зарплату, что требует достаточно больших вложений и времени. Например, у меня уходило на написание статьи от 2-3 дня, а если требовалось написать код к статье как минимум 2 недели. Интерфейс пошел более коротким путем - стал брать с сайтов информацию, а потом ее выдавать как свою собственную, дополняя ее рекламой. 

  Вывод 2. Никаких авторских ссылок Интерфейс не делает. Это полная демагогия. Вот пример как выглядит прямая ссылка на сайт http://www.leadersoft.ru. Что делает Интерфейс для того чтобы "убить ссылку" для поисковых систем. Во первых, у ссылки безжалостно отрезается домен и другая важная интернет- информация, и она превращается в обычный текст  leadersoft. На втором этапе, вместо прямой ссылки на сайт дописывается что-то типа этого (... goto.asp?Url=enc:rn%7Ej%40%255bofz%24v%5Fk%5Eohyeln4h%7F%...kizr), на третьем этапе они ее размещают не внутри статьи, а после своей рекламы. Таким образом у читателя создается полная иллюзия того, что эта статья Интерфейса. Не брезгует Интерфейс еще и тем, что "ломает" ссылки, т.е. среди ссылок есть и не рабочие.  Достаточно грязный подход к вопросу о ссылках вообще. Ясно, что за статью Интерфейс вам ничего не отдаст, даже ссылку интернета.
 
   Вывод 3. Зачем Интерфейс маскирует ссылки на автора. Вывод один - увеличение собственного рейтинга. Современные роботы интернета умеют анализировать информацию стараясь в начале поиска выдавать свежую и уникальную информацию. Например, если Вы написали статью, и точно такую же статью вдруг опубликует другой сайт, то ей может быть присвоен очень низкий рейтинг. Таким образом, защищается информация от "подделки".  Если такой информации много, то всему сайту будет присвоен низкий рейтинг, и его достаточно сложно обнаружить в поиске. С этим достаточно часто сталкиваются разработчики интернет - магазинов по партнерской программе, когда указывают прямые ссылки на товары парт��ера. С другой стороны, если будут прямые ссылки на автора, но рейтинг его сайта будет увеличиваться, а это Интерфейсу не выгодно.

   Вывод 4. Зачем Интерфейс старается максимально полно скопировать статью, а не давать ей краткую характеристику. Главная цель - это изменение индекса поисковых систем. Чем больше статей с различной информацией, тем больше вероятность того, что индекс поисковой системы будет изменен. Это легко проверить. Попробуйте поискать вашу статью в интернете и Вы заметите, что статьи Интерфейса (!!!) имеют больший "вес", чем ваши. Хотя собственных статей у Интерфейса очень мало. Проверьте также и собственную статистику сайта по посещаемости. В базе данных я не нашел ни одной ссылке с Интерфейса за несколько лет.

   Вывод 5. Бороться с такими компаниями типа Интерфейс очень сложно. Защитить интернет статью, как программу - невозможно, да и общественные правила на них не действуют. Хотя некоторые шаги для решения этой проблемы можно сделать. Я, например, обратился в  http://www.nic.ru, где получил подробный ответ от Токаревой Ксении, юрисконсульта АНО "РСИЦ". Обратите внимание на выделенный текст - очень умное решение.

   АНО "РСИЦ" является регистратором для домена interface_ru Услуги хостинга для сайта www_interface_ru АНО "РСИЦ" не предоставляет. АНО "РСИЦ" как регистратор домена interface_ru вправе применить к администратору (владельцу) домена только действия, прямо предусмотренные Регламентом регистрации доменов в домене RU (http://www.nic.ru/dns/contract/sup1_1_ru.html). Администратор домена самостоятельно определяет порядок использования домена; несет ответственность за выбор доменного имени, возможные нарушения прав третьих лиц, связанные с выбором и использованием доменного имени, а также несет риск убытков, связанных с такими нарушениями.
Вопросы создания сайта и размещения на нем информации относятся к вопросу использования домена, а не к вопросу его регистрации. Регистратор не вправе вмешиваться в отношения Администратора домена с третьими лицами, возникающими при использовании домена. Если обращение к Администратору домена не помогло, Вы вправе в суд с иском о защите авторских прав к Администратору домена. Перед обращение в суд рекомендуем заверить содержание сайта www_interface_ru у нотариуса в порядке обеспечения доказательств. Сведения об Администраторе домена для подачи иска в суд (паспортные данные, почтовый адрес) могут быть предоставлены АНО "РСИЦ" в порядке и случаях, предусмотренных действующим законодательством, в том числе по запросу адвоката.


   Я бы добавил к этому еще несколько писем. Например, можно их отправить по следующим адресам в
:
1) http://www.yandex.ru о нарушении рейтинга. Интерфейс находится у них на первом месте по базам данных, и видно, что этот рейтинг накручен статьями.
2)
https://www.google.com/webmasters/tools/spamreport?hl=ru об интернет спаме. 
3)
http://www.subscribe.ru о дублировании статей. Интерфейс использует данный ресурс для рассылки рекламной информации под видом статей о базах данных. Для них это важная проблема. Они же теряют на этом авторов и рекламная аудитория - уменьшается

  Вывод 6. О подготовке специалистов Интерфейсом. Компания не имеет серьезной собственной научной базы и преподавателей, пройдя у них обучение Вы просто впустую потратите свои деньги. Знаний Вы не получите. С другой стороны, если Вы имеете на руках свидетельство об образовании Интерфейса, то не показывайте документ работодателю. Ему может не понравиться ваши контакты с данной компанией.

  Вывод 7. О покупке программных продуктов. Не рискуйте и не покупайте у них программные продукты. Может оказаться, что Интерфейс продаст Вам их с нарушением авторских прав. Деньги потом вернуть будут очень сложно. Тем более сейчас много компаний, которые продают программы дешевле.

  Заключение.
   Вы можете оставить комментарий ниже

Словарь терминов по статье
  
Полнотекстовый поиск
   Любая поисковая система будь-то yandex или google обладает полнотекстовым поиском (формулировка взята из Microsoft SQL Server). Суть такого поиска. При больших объемах информации эффективный поиск в базе данных даже для SQL Server становиться медленным. Это заметно при поиске в нескольких сотнях тысячах записей. Например, использование в SQL запросах LIKE может привести к задержке выдачи информации от 1 секунды и более. Чтобы этого не было необходимо создать индекс, при этом его желательно хранить не в самой базе данных файле mdf, а лучше в отдельных файлах Операционной системы. Использование полнотекстового индекса позволяет искать и слова по смыслу. Для этого есть специальные команды для языка T-SQL. После индексации сайта поиск выполняется очень быстро, менее чем за 1 секунду.
Партнерская программа
   Для раскрутки своего сайта многие поставщики товаров используют сайты партнеров. Информация о товарах располагается не только на своем сайте, но и у партнеров. Для загрузки информации используются xml файлы в формате yandex market или Microsoft Excel. Оплата услуг производится по факту продажи. Размещать ссылки на сайте нужно аккуратно, чтобы не ухудшить индекс сайта..
Поисковый робот
   Поисковый робот интернета (bot) - это специальная компьютерная программа для обработки текстовой и графической информации с сайтов. Чаще всего она работает не одна и может запускать сразу с разных поисковых серверов даже одного сайта. В день может скачивать несколько тысяч страниц с объемом трафика в 1ГБ и более. Как правильно разработать сайт, чтобы он был просканирован быстро роботами - это отдельная наука. Лучше эту работу доверить профессионалам.

Выпуск 92. Сложение данных из символьных полей в запросе

Новости проектирования баз данных. 

1. Разработана база данных для Московского офиса фармацевтической компании из Индии. Цель проекта учет и контроль медицинских представителей. Так пользователей достаточно много (>500), то решение было сделано создать распределенную базу данных на базе Microsoft Access + SQL Server (Msde). Вся информация из регионов России автоматически архивируется и посылается в базу данных центрального офиса. Загрузка также ведется автоматически. При этом не требуется наличие архиватора и почтовой программы у представителя. Все это делается встроенными средствами Windows, поэтому затрат на покупку дополнительных программ не потребовалосьБаза данных позволяет собирает различную коммерческую информацию медпредставителей о посещениях лечебных учреждений и аптек и подготавливает большое количество отчетов в Access, Excel с графиками. Позволяет оперативно реагировать на изменение и потребление рынка лекарств в России.

2. Разработана база данных для компании Сириус. Цель проекта создать базу данных по приему заказов через Интернет и обработке их в офисе компании. Средства разработки ASP.NET + SQL Server (web интерфейс), а для пользователей офиса - на Access + SQL Server. Почему выбрано такое технологическое решение? Главное это то, чтобы отказаться от разных баз данных (MySQL, Mdb, Email). Обслуживание таких баз данных требует много времени. В данном решении имеется только одна база данных SQL Server, а следовательно вся информация которая поступает из Интернета или офиса хранится в одном месте. Это упрощает поиск, повышает надежность сиcтемы, исключает время на обработку электронных писем. С другой стороны с базой данных вы можете работать удаленно, так и внутри офиса и получать типовые отчеты: накладные, счета - фактур и т.п. 


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

Автор. Дмитрий Сонных

Сложение данных из символьных полей в запросе с группировкой - аналог функции Sum()

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

      Создаем в базе две таблицы - таблицу зданий tblOsnFond и таблицу материалов tblMaterial. Потом создаем третью таблицу tblOFmaterial, куда будем заносить связь между строениями и мотериалами, из которых оно построено. Всё довольно стандартно. Легко получить список материалов, из которых сделано строение, и легко получить список строений, в котором используется определенный материал. Но вот настала пора создавать отчет (или форму), в котором должен быть столбецы (поля) "Строение" и  "Материалы", В поле "Материалы" должны быть перечислены все материалы, которые были использованы при строительстве. Использовать в запросе функцию Sum() для сложения (слияния) символьных значений не представляется возможным потому, что функция Sum() применима только для скалярных(!!!) значений. А для символьных она не работает. И действительно:

      3+2=2+3, но "3"+"2"<>"2"+"3" "32"<>"23"

      Для того, чтобы сложить значения символьного поля надо самому написать функцию сложения символьных (string) значений и подставить её в запрос. Эта функция должна быть расположена в отдельном модуле (а не в модуле формы или отчета) и иметь свойство Public Такую функцию уже можно подставлять в запрос. Вот пример функции:

Public Function fnSumString(LngOsnFond As Long) As String

Dim sResult As String

On Error GoTo fnSumString_Error
Dim RstX As ADODB.Recordset
Dim strSQL As String

       Set RstX = New ADODB.Recordset
       strSQL = "SELECT * FROM qryOFmaterial WHERE IdOsnFond=" & LngOsnFond

       RstX.Open strSQL, CurrentProject.Connection, adOpenKeyset
 
       ' первоначальное присвоение значения
       sResult = ""
       ' проверка на наличие записей в запросе
       If RstX.RecordCount > 0 Then
              Do
                     sResult = sResult & (IIf(Len(sResult) > 0, ", ", "") & Nz(RstX.Fields("Material"), ""))
                     RstX.MoveNext
              Loop Until RstX.EOF 
       End If
       RstX.Close
       Set RstX = Nothing
       fnSumString = sResult

On Error GoTo 0
       Exit_fnSumString:
       Exit Function

fnSumString_Error:
       MsgBox "Ошибка " & Err.Number & " (" & Err.Description & ") в процедуре fnSumString в Module Module1"
       Resume Exit_fnSumString
End Function

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

SELECT qryOFmaterial.IdOsnFond, qryOFmaterial.OsnFond, fnSumString(qryOFmaterial.IdOsnFond) AS MaterialSum
FROM qryOFmaterial
GROUP BY qryOFmaterial.IdOsnFond, qryOFmaterial.OsnFond;

      Вот собственно и всё. Но поскольку сейчас многие начинают переходить на MS SQL Server, то следует рассказать как эта задача решается и там. Там тоже используется пользовательская функция, но не написанная в программе, а хранимая на сервере. Решает она те же самые задачи. Вот её текст:

ALTER FUNCTION [dbo].[fn_OFmaterialS]
(@id INTEGER)
RETURNS NVARCHAR(100)
AS
BEGIN
      DECLARE @Result NVARCHAR(4000)
      SET @Result = ''
      SELECT @Result = @Result + case when [Material] Is null then '' else case when @Result<>'' then ', '+[Material] else       
            [Material] end end
      FROM vw_OsnFondMaterial WHERE [IdOsnFond] = @Id
      RETURN  @Result
END

Используемые источники:

Сайт HIPROG.COM Слияние полей из разных строк запроса
Сайт SQL.RU Сложение символьных полей в запросе

Ну и справочники и учебники по Access и MS SQL Server. К статье приложен небольшой пример в формате Access 2000.

Комментарий от  http://www.leadersoft.ru/

В современных языках программирования (VBA) аналогичные задачи решает функция Evаl. Пример правильного выражения:  Eval("2*30+32-345.456+sin(0.2)"). Для ASP.NET эта функция возвращает еще данные и из таблиц базы данных. Для SQL запросов такой функции нет, поэтому ее надо придумать, использовать предложенный выше вариант. Еще замечание. Если вам нужно разработать высокоскоростное решение для больших баз данных, то придумать его на языке SQL не так-то просто. Нужно использовать индексы и временные таблицы, иначе простая построчная обработка записей (например, через курсоры) займет много времени.

Выпуск 91. Препроцессор, или как дважды определить одну функцию в VBA

 
Вступление 
    Препроцессор - это средство разработки программ было заимствовано из языка С. Он использовался для разработки операционных систем. Суть его - это сокращение программного кода, путем обработки нужных фрагментов кода еще до процесса компиляции.
    Синим цветом показаны, команды относящиеся к препроцессору. Он первым начинает обработку программного кода. После его прохода на выходе, используя #If - Else будет создан нужный нам текстовый файл. После этого компилятор превратит код VBA в машинный код.
    Для того, чтобы понять как работает препроцессор рассмотрим несколько примеров.

Пример 1. Компиляция базы для Vista

  Вы решили использовать ссылки на Word, Excel, Outlook. К сожалению на OS Vista это может вызвать проблемы из-за того, что они неправильно будут обрабатываться в mde и ade  проектах. Вам надо будет привязывать ссылки в момент вызова приложения CreateObject("Application.Word"), а не через References в VBA (New Application.Word). Управлять и писать код на VBA в первом варианте - невозможно. У офисных приложений много переменных, а в варианте с CreateObject мы их не видим. Суть решения - ставим ссылку на Word и решаем задачу. Далее копируем фрагменты кода и заменяем типы переменных на object.
 Заключение. Для создания рабочей версии базы данных для пользователей снимите ссылку в VBA на Word, приравняйте  WordRef = 0, создайте проект mde или ade. В этом случае база данных будет работать и в XP и в Vista для офисов 2000, 2002, 2003, 2007


#Const WordRef
= 1 ' !!! Константа действует только в текущем модуле.
#If WordRef = 1 Then
   Dim app As New Word.Application
   Dim rng As Word.Range ' Область данных
   Dim tbl As Word.Table ' Таблица документа
#Else
   Dim obj As Object
   Set obj = CreateObject("Word.Application")
   Dim rng As Object ' Область данных
   Dim tbl As Object ' Таблица документа
#End If
 

Пример 2. Двойное определение функций

Нам надо в Word вставить таблицу или запрос из базы данных. Это делает функция InsertDatabase. При этом в версии A2000 - она имела одни параметры, а в Access 2002 - другие. Изменилась строка соединения. Если не использовать препроцессор, то придется писать несколько баз данных для разных версий. Понятно, что работать с одной базой значительно проще, чем управлять несколькими.


#Const AccessVer = 2003 ' !!! Константа действует только в текущем модуле.
' Вставляем таблицу, используя запрос из базы данных
#If AccessVer = 2000 Then
.InsertDatabase _
Style:=191, _
LinkToSource:=False, _
Connection:="Query ЗапросПримера04", _
DataSource:=strMDB
#Else
.InsertDatabase Format:=0, Style:=0, LinkToSource:=False, _
Connection:= _
"Provider=Microsoft.Jet.OLEDB.4.0;Password="""";User ID=Admin;Data Source=" & strMDB & ";Mode=Read;Extended Properties="""";Jet OLEDB:System database="""";Jet OLEDB:Registry Path="""";Jet OLEDB:Database Password="""";Jet OLE" _
, SQLStatement:="SELECT * FROM `ЗапросПримера04`" & "", PasswordDocument _
:="", PasswordTemplate:="", WritePasswordDocument:="", _
WritePasswordTemplate:="", DataSource:= _
strMDB, From:=-1, To _
:=-1, IncludeFields:=True
#End If


Пример 3. Создание демоверсии

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


#Const DemoVer = 1 ' !!! Константа действует только в текущем модуле.
#If DemoVer = 1 Then
   Dim MaxRecords = 10 ' Можно читать только 10 записей из таблиц
 #Else
   Dim MaxRecords = 0 ' Нет ограничений на чтение записей
#End If
 

 

Выпуск 89. Часто встречающиеся вопросы при проектировании БД

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

Автор. Парусников Алексей

Часто встречающиеся вопросы при проектировании БД.

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

1. Соглашения об именах полей, элементов управления и объектов

 1.1. Пробелы в именах

      Вот общие правила (согласно Help), которых следует придерживаться:

  • имя должно содержать не более 64 знаков;
  • имя может включать любую комбинацию букв, цифр, пробелов и специальных знаков за исключением точки (.), восклицательного знака (!), надстрочного знака (`) и квадратных скобок ([ ])
  • не должно начинаться с знака пробела
  • не должно включать управляющие знаки (с кодами ASCII от 0 до 31)
  • не должно включать прямые кавычки (") в именах таблиц, представлений и сохраненных процедур в проекте Microsoft Access.

      Дело в том, что если с именами предполагается работать с помощью процедур VBA, то в некоторых случаях будет довольно проблематично обращаться к имени объекта, если оно содержит пробелы. Например, при обращении к имени с пробелом, его нужно заключать в квадратные скобки, что не совсем удобно. Но в некоторых выражениях скобки не допустимы. В результате придется переименовывать объект, что часто влечет за собой большие проблемы с работой программы, или искать «обходные пути». Поэтому, лучше выбрать один из вариантов:

ИмяОбъекта
Имя_Объекта

1.2. Кириллица или латиница?

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

      программа, в которой для названия объектов используются национальные символы, НЕ БУДЕТ РАБОТАТЬ в системе, в которой нет поддержки этого языка.

      Особенно это касается кириллицы (русский алфавит). Именно по этой причине разработчики, которым приходится работать на разных версиях офиса (и тем более за границей) настаивают на использовании английских имен. Однако, иногда одной лишь замены символов бывает не достаточно – чтобы приложение 100% работало в английской версии, оно должно быть создано в АНГЛИЙСКОЙ ВЕРСИИ офиса. Кроме того, использование кириллицы создает проблемы:

  • при использование сторонних утилит – они могут не работать с русскими названиями объектов. Но даже и «со своими» функциями может быть проблема. Попробуйте, к примеру, создать функцию в модуле формы, и вызвать ее, прописав в свойствах формы на какое либо ее  событие =Моя_Функция(). Access ее «не увидит». Хотя, если обратиться к той же функции в коде модуля – все работает. Это говорит о том, что полной русификации нет.
  • постоянное переключение раскладки клавиатуры. У многих это вызывает раздражение.
  • если вы планируете работать за рубежом (или с английскими версиями программ), то имеет смысл приучать себя к общепринятому стандартному обозначению имен объектов.

      Прочитав вышесказанное, создается впечатление, что на вопрос, как называть объекты БД, ответ очевиден, однако не все так просто. Для начала глянем на соседей.

      Кто работал за границей, тот знает, что немцы практически всегда называют объекты по-немецки, а французы по французски и т. д., да и вообще европейцы в этом смысле не дисциплинированны (как, впрочем, и все остальные). Стало быть, если им можно, почему нам нельзя? Хотя им конечно проще – у них латинский алфавит. Ну а если серьезно, то использование национальных названий имеет и свои преимущества:

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

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

1.3. Собственная система обозначений

      Разобравшись с алфавитом, перейдем теперь к именам. Вот основные правила, на которых сходятся все разработчики:

  • называйте объекты БД, используя осмысленные имена и префиксы, по которым можно будет определить, к какой группе относится объект. В окне проекта они отсортируются по алфавиту, что значительно облегчит понимание (и вспоминание через какое то время) структуры базы данных
  • старайтесь придерживаться однообразной системы обозначений (если ее нет - придумайте). Так вы значительно облегчите себе (и другому, кто будет разбираться в ваших творениях потом) разбор структуры базы

      Вот пример системы, используемой «ПрограммистЛюбитель» (часто появляется на SQL.ru)

Я именую все объекты БД и в коде программы по-английски. Если не знаю точный перевод слова - лезу в лингво. Плюс «венгерская нотация» - префиксы. Стараюсь придерживаться однообразной системы при именовании запросов, полей таблиц.

Для запросов префиксы:

qr - обычный запрос делающий SELECT из одной/нескольких таблиц
sel - фильтрующий только уникальный записи по части полей
sum - суммирующий/агрегатирующий данные
pvt - перекрестный/сводный запрос
ins - на вставку данных
upd - на обновление данных

Для полей таблиц:

<префикс> + <корень таблицы> + <доп. слово-описание, иногда два>
i<Корень - имя таблицы>ID - счетчик, почти всегда PrimaryKey
i<Корень>Code - уникальные коды не счетчик, часто PrimaryKey
s<Корень>Code - уникальные буквенные коды
i<Корень>Nomer - номера по порядку
s<Корень>Name, s<Корень>Description, s<Корень>Comment - думаю, ясно
n<Корень>Count - количестко чего-либо
dt<Корень>Birthday, dt<Корень>From, dt<Корень>To и т.п. – даты

      Но в тоже время, часто используют смешанный тип обозначения. Например:

Имена объектов – префиксы объектов на английском, имена на русском
Имена модулей, функций, процедур – на английском
Имена полей таблиц – префиксы на английском, имя поля на русском

      В результате получается:

Имена полей таблицы типа: id, idПоставщик, sПримечание и т. д.
Имена запросов: qryRptСводка_сдачи, qrySumИтог_продаж и т. д.

      Хотя такой подход многие называют «дурным тоном», тем не менее, он довольно часто имеет место. Видимо дело все в том же: так легче визуально искать объект, а английский префикс выделяется среди русских букв, облегчая понимание. И даже переключение раскладки клавиатуры не останавливает.

Вывод:

      В конечном итоге, как называть объекты базы данных – это личное дело разработчика, и во многом зависит от того, ЧТО он пишет, ДЛЯ КОГО и ЗАЧЕМ. При этом помните о возможных проблемах, если используете кириллицу. Но, главное:

      Используйте для обозначения объектов БД осмысленные имена в соответствии с соглашением об именах объектов. При этом, крайне желательно придерживаться какой либо системы обозначений – это значительно облегчит понимание структуры базы.


Дополнение от www.leadersoft.ru .
    Если Вы делаете проект
adp проект. Он применяется, когда Вы разрабатывает базу данных на Access+SQL Server, то желательно все объекты называть и по имени проекта. Например, market_, student_, dnn_ и т.п. это позволит Вам избежать конфликта объектов. Например, Вы используете CRM систему сайта Dotnetnuke, то в ней может быть несколько десятков, а то и сотен объектов (зависит от установленных модулей). В таком количестве объектов очень легко потеряться. Префикс проекта, позволит Вам быстро найти нужный объект: таблицу, запрос, процедуру и т.п. Пример. Таблица: Market_Products, процедуры:  Market_UpdateProduct, Market_DeleteProduct, Market_InsertProduct. Объекты CRM системы желательно начитать с dnn_forum_ .. P.S. К сожалению интерфейс Access и менеджер баз данных  SQL Server не позволяет группировать объекты в дерево. Хотя это давно уже надо было бы сделать разработчикам.

Примеры перевода.
Конвертор отчетов Crystal Reports 
Добрый день. Я в настоящее время использую сервер отчетов с Crystal Reports XI Server. Но сам процесс обработки данных идет слишком медленно, мне нужен специалист, кто смог бы мне решить эту проблему. Бюджет $300-$1000, Знания: JSP, Programming 

Портал по работе 
Уважаемые специалисты, мне нужен портал по работе, который будет клоном сайта http://www.bdjobs.com/. Функционально он должен быть уникальным. Этот проект должен быть разработан и создан с использованием Joomla 1.5 ... (Бюджет $1000 - $3000)


 

Выпуск 87. Вызов системных компонентов из VBA

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

Автор. Дмитрий Сонных

Вызов системных компонентов из VB/VBA.

      Иногда бывает необходимо просмотреть или изменить системные настройки Windows. И хочется это сделать сразу из программы, а не через «Пуск --> Панель управления --> Нужные настройки…»

      Для большинства системных установок Windows предлагает свои компоненты. Существует несколько десятков окон, предлагающих что-либо изменить в системе. Каждое из таких окно можно вызвать из VB, не используя ни одной API-функции. Наборы таких окон находятся в библиотеках Windows'a с расширением ".cpl". Например в библиотеке desk.cpl находятся четыре стандартных окна (точнее одно окно с четырмя закладками): "Фон", "Заставка", "Настройка", "Оформление" (В Windows XP добавилась пятая закладка «Темы»). Для того, чтобы вызвать не просто нужное окно, а ещё и нужную закладку, в параметрах вызова надо установить индекс нужной закладки. Вызов происходит при помощи обычной функции Shell, но немного необычным способом:

Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl, ,0" )

      Откроет окно свойств экрана с закладкой "Фон". А теперь некоторые библиотеки и параметры. Только надо учесть, что состав библиотек и параметров могут зависеть от версии Winduws. Там, где возможно, я укажу отличия.

Экран - desk.cpl

- фон/Рабочий стол = "desk.cpl, ,0"
- заставка = "desk.cpl, ,1"
- оформление = "desk.cpl, ,2"
- настройка/параметры = "desk.cpl, ,3"
- темы = "desk.cpl, ,5" (Windows XP)

Специальные возможности – access.cpl

- клавиатура = "access.cpl, ,1"
- звуки = "access.cpl, ,2"
- экран = "access.cpl, ,3"
- мышь = "access.cpl, ,4"
- общие = "access.cpl, ,5"

Главная - main.cpl, используется для управления мышью, клавиатурой, принтерами, шрифтами.

- мышь = "main.cpl @0"
- кнопки мыши = "main.cpl @0,0" (Windows 2000/XP)
- указатели мыши = "main.cpl @0,1" (Windows XP)
- параметры указателя мыши = "main.cpl @0,2" (Windows XP)
- колесико мыши = "main.cpl @0,3" (Windows XP)
- оборудование = "main.cpl @0,4" (Windows XP)

      В Windows 2000 не смог переключить вкладки. Вместо @0 можно подставить следующие значения и получить, соответственно:
- клавиатура =”main.cpl @1”

      и для ХР

- скорость =”main.cpl @1,0” (Windows 98/2000)
- язык =”main.cpl @1,1” (Windows 9x/2000)
- оборудование =”main.cpl @1,1” (Windows XP)
- оборудование =”main.cpl @1,2” (Windows 2000)
- принтер =”main.cpl @2” (Windows 9x)
- шрифт =”main.cpl @3” (Windows 9x)

Язык и региональные параметры – intl.cpl

- региональные стандарты/региональные параметры = “intl.cpl,,0” (Windows 9х/ХР)
- общие = “intl.cpl, ,0” (Windows 2000)
- числа = “intl.cpl, ,1” (Windows 9х/2000) (в Windows XP на вкладке «региональные параметры»)
- языки = “intl.cpl, ,1” (Windows XP)
- денежная единица = “intl.cpl, ,2” (Windows 9х/2000) (в Windows XP на вкладке «региональные параметры»)
- дополнительно = “intl.cpl, ,2” (Windows XP)
- время = “intl.cpl, ,3” (Windows 9х/2000) (в Windows XP на вкладке «региональные параметры»)
- дата = “intl.cpl, ,4” (Windows 9х/2000) (в Windows XP на вкладке «региональные параметры»)
- языки и раскладка = “intl.cpl, ,5” (Windows 2000)

Дата и время - timedate.cpl

- дата и время = "timedate.cpl, ,0"
- часовой пояс  = "timedate.cpl, ,1"

Модем - modem.cpl

- модемы = "modem.cpl" (Windows 9х – две вкладки, переключить не удалось) (вкладка «модемы» на форме «Телефон и модем» в Windows 9х/2000/XP)

Телефон и модем - telephon.cpl

- набор номера = "telephon.cpl, , 0"(Windows 2000/XP)
- модемы = "telephon.cpl, ,1"(Windows 2000/XP)
- дополнительно = "telephon.cpl, ,2"(Windows 2000/XP)
В Windows 9х две вкладки. Переключить не удалось

Сеть/конфигурация - netcpl.cpl  (Windows 9х)

Три вкладки. Переключить не удалось.
Мастер настройки сети –netsetup.cpl (Windows XP)

Факс – fax.cpl (Windows 2000/XP)

- сведения о пользователе = "telephon.cpl, ,0"
- титульные страницы = "telephon.cpl, ,1"
- монитор состояния = "telephon.cpl, ,2"
- дополнительные параметры = "telephon.cpl, ,3"

Система - sysdm.cpl

- общие = “sysdm.cpl, ,0”
- устройства = “sysdm.cpl, ,1” (Windows 9х)
- сетевая идентификация = “sysdm.cpl, ,1” (Windows 2000)
- имя компьютера = “sysdm.cpl, ,1” (Windows XP)
- профили оборудования = “sysdm.cpl, ,2 (Windows 9х)
- оборудование = “sysdm.cpl, ,2 (Windows 2000/ХР)
- быстродействие = “sysdm.cpl, ,3” (Windows 9х)
- профили пользователей = “sysdm.cpl, ,3” (Windows 2000)
- дополнительно = “sysdm.cpl, ,3” (Windows XP)
- дополнительно = “sysdm.cpl, ,4” (Windows 2000)
- восстановление системы = “sysdm.cpl, ,4” (Windows XP)
- автоматическое обновление = “sysdm.cpl, ,5” (Windows XP)
- удаленные сеансы = “sysdm.cpl, ,6” (Windows XP)

Служба автоматического обновления wuaucpl.cpl (Windows 2000)

Пароль - password.cpl (Windows 9х)
Три закладки. Переключить не удалось.
В Windows 2000 за пользователей отвечает модуль netplwiz.dll, который таким путем вызвать нельзя
Учетные записи пользователей - nusrmgr.cpl (Windows XP)

ODBC - odbccp32.cpl

- пользовательский DSN = "odbccp32.cpl, ,0"
Переключить на другие закладки не получилось.

Установка и удаление программ - appwiz.cpl

- установка/удаление программ - "appwiz.cpl, ,0" (Windows 9х)
- изменение или удаление программ - "appwiz.cpl, ,0" (Windows 2000/XP)
- установка компонентов Windows - "appwiz.cpl, ,1"  (Windows 9х)
- установка программ - "appwiz.cpl, ,1"  (Windows 2000/XP)
- загрузочная дискета - "appwiz.cpl, ,2" (Windows 9х)
- установка компонентов Windows - "appwiz.cpl, ,2" (Windows 2000/XP)
- выбор программ по умолчанию - "appwiz.cpl, ,3"  (Windows 2000/XP)
Для Windows 9x переключить вкладки не удалось.

Мультимедия - mmsys.cpl

- аудио = "mmsys.cpl,,0" (Windows 9х)
- звук = "mmsys.cpl,,0" (Windows 2000)
- звуки и аудиоустройства = "mmsys.cpl,0" (Windows XP)
- громкость = "mmsys.cpl,,0" (Windows XP)
- видио = "mmsys.cpl,,1" (Windows 9х)
- аудио = "mmsys.cpl,,1" (Windows 2000)
- звуки = "mmsys.cpl,,1" (Windows XP)
- миди = "mmsys.cpl,,2" (Windows 9х)
- оборудование = "mmsys.cpl,,2" (Windows 2000)
- аудио = "mmsys.cpl,,2" (Windows XP)(включает в себя вкладку миди из 9х)
- компакт - диск = "mmsys.cpl,,3" (Windows 9х)
- речь = "mmsys.cpl,,3" (Windows XP)
- оборудование = "mmsys.cpl,,4"  (Windows XP)

Джойстик - joy.cpl

- игровые устройства = "joy.cpl, ,0" (Windows 9x/2000)
- идентификаторы устройств = "joy.cpl, ,1" (Windows 9x/2000)
В Windows XP вкладок нет

Сканеры и камеры sticpl.cpl (Windows 9х/2000)

DirectX (если он установлен) - directx.cpl
Имеет 8 вкладок (DirectX 9c). Приводить их не буду. Вряд ли Вы будете настраивать DirectX из своих программ.

Брандмауэр Windows - firewall.cpl (Windows XP)

- общие = "firewall.cpl, ,0"
Всего три вкладки. Переключить их не удалось.

Мастер установки оборудования - hdwwiz.cpl (Windows 2000/XP)

Электропитание - powercfg.cpl

- схема управления питанием = "powercfg.cpl, ,0"
Всего четыре (Windows 98 – 2)  вкладки. Переключить их не удалось.

Параметры оповещения - wscui.cpl (Windows XP)

Сетевые подключения - ncpa.cpl (Windows 2000/XP)

Свойства очереди подключений - msmq.cpl (Windows 2000)

- запоминающие устройства = "msmq.cpl, ,0"
Есть три вкладки. Переключить не удалось.

Интернет - inetcpl.cpl

- общие ="inetcpl.cpl, ,0"
- безопасность ="inetcpl.cpl, ,1"
- конфиденциальность ="inetcpl.cpl, ,2"
- содержание ="inetcpl.cpl, ,3"
- подключения ="inetcpl.cpl, ,4"
- программы ="inetcpl.cpl, ,5"
- дополнительно ="inetcpl.cpl, ,6"
Экран настройки зависит от версии IE. Здесь дан экран для IE 6.0.

      Некоторые программы тоже помещают свои экраны настройки в системный раздел Windows (например, Java - jpicpl32.cpl)
Другие программы хранят свои экраны настройки в своих папках. Их можно так же запустить через Shell

Call Shell("rundll32.exe shell32.dll,Control_RunDLL имя_файла.cpl,0" )

      Но в этом случае имя файла должно указываться с полным путем. Поскольку названия папок могут содержать пробелы, то можно привести его к DOS виду. Например, отрыть экран настройки конфигураций почты Outloоk можно так

Call Shell("rundll32.exe shell32.dll,Control_RunDLL _
G:\PROGRA~1\COMMON~1\System\MSMAPI\1049\MLCFG32.CPL,,")

      Или заключить путь в две пары двойных кавычек

Call Shell("rundll32.exe shell32.dll,Control_RunDLL _
""g:\Program Files\Common Files\System\MSMAPI\1049\MLCFG32.CPL"" ,,")

      Из-за того, что в разных версиях Windows состав экранов управления различен, причем иногда различны и закладки на этих экранах, к использованию экранов настройки Windows надо подходить с осторожностью. Желательно сначала определить используемую версию Windows.

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

Public Sub ShellSysComp(strLibName As String, intIndex As Integer)
      Call Shell("rundll32.exe shell32.dll,Control_RunDLL " + strLibName + ",," + LTrim(Str(intInddex)))
End Sub

      Эта подпрограмма всего лишь соединяет имя библиотеки с индексом, переведённым в строку, и запускает всё это дело. Используемые материалы: сайт www.sdteam.com, Сергей Миллер, «Вызов системных компонентов из VB»

Выпуск 86. Каскадное автозаполнение списков

Дорогие друзья, поздравляем вас с наступающим Новым годом и Рождеством!

Хотим пожелать вам в наступающем году успехов, счастья и благополучия!


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

Автор. Парусников Алексей

Каскадное автозаполнение списков

      В опубликованной ранее статье «Справочники» кроме описания процесса и краткой теории создания справочных форм и таблиц также приводился пример использования функции AppendLookupTable, позволяющей добавлять отсутствующее значение в список. Добавление происходило автоматически после прямого ввода нужного значения в список. Однако эта функция позволяла добавлять данные только в одиночный список. На практике же довольно часто бывает необходимость подобного автозаполнения, но уже связанных (зависимых) списков. О варианте решения – доработке функции AppendLookupTable и пойдет речь в этой статье.

      Для рассмотрения примера создадим три справочных таблицы:

Имя таблицы

Имя поля

Тип поля

Связанная таблица

Поле в связанной таблице

Страны

id_Страны

Счетчик

 

 

Страна

Текст

 

 

Производители

id_Компании

Счетчик

 

 

id_страны

Числовое (длинное целое)

Страны

id_Страны

Компания

Текст

 

 

Товары

Id_товара

Счетчик

 

 

id_компании

Числовое (длинное целое)

Производители

id_Компании

Товар

Текст

 

 

      Индексируем поля таблиц для получения возможности автоматического отслеживания уникальности значений. В противном случае может случится, что одно и то же значение в справочнике повторяется. Для этого открываем таблицу в режиме конструктора, жмем на значок в меню «Индексы» (значок молнии). В появившемся диалоговом окне в поле «Индекс» пишем название индекса (любое), например «Страна». Затем в поле «Имя поля» выбираем из списка «Страна» и в нижней части формы выбираем из списка «Уникальный индекс» - Да. Теперь при попытке ввести уже существующее значение появится соответствующее сообщение и ввод будет заблокирован.

      В таблицах «Производители» и «Товары» индекс должен быть составной, так как нужно отслеживать уникальность пары Страна – Производитель. Ведь разные страны могут выпускать одинаковые товары. Пример создания составного индекса:

Имя таблицы

Имя индекса

Имя поля

Индекс

Страны

Страна

Страна

Уникальный индекс - Да

Производители

Компания

id_страны

Уникальный индекс - Да

Компания

Товары

Товар

id_компании

Уникальный индекс - Да

Товар

      Связываем отношением один ко многим справочные таблицы: Страны – Производители – Товары. Таким образом получили систему из трех связанных справочников, в которой кроме данных устанавливаются так же зависимости между таблицами. Создадим так же для демонстрации примера автозаполнения две рабочих таблицы: Заказы и Список товаров.


Имя таблицы

Имя поля

Тип поля

Связанная таблица

Поле в связанной таблице

Заказы

id_Заказ

Счетчик

 

 

id_страны

Числовое (длинное целое)

 

 

id_Компании

Числовое (длинное целое)

 

 

Список товаров

id_Список

Счетчик

 

 

id_Заказ

Числовое (длинное целое)

Заказы

id_Заказ

Id_товар

(длинное целое)

Товары

Id_товара

Связываем таблицы «Заказы» и «Список товаров» соотношением один ко многим по полям «id_Заказ» (на один заказ может быть много товаров).
Теперь рассмотрим вариант создания формы – справочника. Можно двумя вариантами:

  1. Сделать справочник «Страны». Потом два справочника: «Страны – производители» и «Производители - товары». Заполняться они должны поочередно: Сначала «Страны», потом «Страны – производители», потом «Производители – товары».
  2. Сделать один двухуровневый справочник: «Страны – производители - товары».

      Во втором случае нужно предусмотреть процедуру, препятствующую вводу данных в форму «Производители», если не заведены данные в форме «Страны». Иначе получим не связанную запись. Для этого служит процедура события формы Enter (Вход).

Private Sub subСправочникПроизводители_Enter()
      If IsNull(Me.id_Страны) Then
            MsgBox "Сначала укажите страну производителя", vbCritical, "admin"
            Страна.SetFocus
      End If
End Sub

      Как видим, при попытке ввести данные в форму, когда не введен ключ от главной формы

If IsNull(Me.id_Страны) Then

      появляется сообщение об ошибке и фокус ввода переносится на поле главной формы. Аналогичная процедура блокировки сделана и для подчиненной табличной формы на форме «Заказы».

      На форме «Заказы» присутствуют два списка: Страны и Производители. Причем второй связан с первым через ссылку на него в запросе (источнике своих данных). Откройте форму «Заказы» в конструкторе и посмотрите на источник строк списка Производитель(id_Компании). На поле id_Страны установлено условие отбора

Eval("Forms!Заказы!id_Страны")

      Аналогично и на поле со списком табличной подчиненной формы «subЗаказы»

Eval("Forms!Заказы!id_Компании")

      Необычное в этих ссылках – это их обработка через функцию Eval(). Но об этом чуть позже.
Справочную форму можно запускать двойным кликом по списку или по меню слева. О реализации подобного интерфейса подробно рассказывалось в статье «Справочники».

      Теперь рассмотрим реализацию каскадного заполнения списков. Как уже говорилось, задача состоит в том, чтобы при автозаполнении связанного списка кроме внесения нового значения в таблицу – источник, нужно так же внести и ключевое значение от главного списка. Иначе получим не связанную запись. По этой причине вводится новая переменная ctl1.

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

Private Sub id_Страны_NotInList(NewData As String, Response As Integer)
      Set ctl = Me!id_Страны 'устанавливаем ссылку на список "Страны"
      ' запускаем функцию каскадного добавления, и в качестве второго аргумента
      ' указываем первый список. То есть функция работает как обычная процедура
      ' добавления в один список
      Response = AppendLookupTable(ctl, ctl, ctl.Text, 0)
      Me.id_Страны.RowSource = Me.id_Страны.RowSource 'обновляем список стран
      Set ctl = Nothing 'очищаем переменную
End Sub

      В этом случае после проверки условия (каскадное или обычное добавление) отсутствующее значение добавляется так же как в старой функции

If cbo.Name = cbo1.Name Then
      Set rst = CurrentDb.OpenRecordset(cbo.RowSource)
      With rst
            .AddNew
            rst(1) = NewData
            .Update
            .Close
      End With

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

Private Sub id_Компании_NotInList(NewData As String, Response As Integer)
      Set ctl = Me.id_Компании 'устанавливаем ссылку на список "Компании"
      Set ctl1 = Me.id_Страны 'устанавливаем ссылку на список "Страны"
      ' запускаем функцию каскадного добавления в два списка
      Response = AppendLookupTable(ctl, ctl1, ctl.Text, Nz(Me.id_Страны, 0))
      Set ctl = Nothing 'очищаем переменную
      Set ctl1 = Nothing 'очищаем переменную
      Me.id_Компании.RowSource = Me.id_Компании.RowSource 'обновляем список компаний
      ' в случае отказа от заполнения
      If Response = 0 Then
            Me.id_Компании = Null 'обнуляем список компаний
            id_Страны.SetFocus  'устанавливаем фокус на список страны
      End If
End Sub

      А теперь по поводу Eval(). Дело в том, что процедура добавления отсутствующего значения в таблицу – источник списка происходит при помощи объектной модели DAO. Если в строке запроса встретится выражение типа Forms!Заказы!id_Страны – будет сообщение об ошибке типа: «Требуется параметр». Потому, что DAO, знать ничего не знает, об открытых формах, именно по этому и ругается. Ему дали строку SQL, он пытается открыть соответствующий рекордсет. Пытается найти поле таблицы с именм Forms! и разумеется не находит.

      Поэтому, когда используется работа с запросом при помощи DAO, то ссылки на элементы форм нужно оформлять через Eval(). Например так:

Eval("Forms!Заказы!id_Страны")

      Или вместо имени приводить сам текст запроса, и в нем указывать ссылку:

Set rst = CurrentDb.OpenRecordset("SELECT Производители.id_Компании, " & _
                                "Производители.Компания, Производители.id_страны " & _
                                "FROM Производители " & _
                                "WHERE Производители.id_Страны = " & Forms!Заказы!id_Страны & _
                                "ORDER BY Производители.Компания")

      Эти рекомендации справедливы и при работе с объектной моделью ADO. Часто первое, на чем спотыкаются те, кто впервые решил перевести свой проект с mdb на adp – это ошибки при выполнении запросов, где есть ссылки на элементы формы. Ведь теперь обработка данных происходит на сервере, на котором нет никаких форм. Впрочем, это уже совсем другая тема, к данной статье не имеющая отношения – переход от mdb к adp.

      В заключение остановлюсь еще на одном вопросе, который так же часто задают начинающие разработчики: как отключить стандартные сообщение Access? Например, при использовании процедуры на удаление записи

DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 6, , acMenuVer70

      если пользователь нажмет «Отмена» будет сообщение: «Прервано выполнение макрокоманды DoMenuItem».
Избавиться от него можно по разному. Например, «оградить» эту процедуру вызова командами отключения/включения стандартных сообщений Access.

DoCmd.SetWarnings False
DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 6, , acMenuVer70
DoCmd.SetWarnings True

      Но в этом случае отключаются все сообщения, а не только «Прервано выполнение макрокоманды DoMenuItem». И если при выполнении «огражденной» процедуры возникнет какая либо другая ошибка – никто об этом «не узнает». А ведь ошибки бывают �� фатальными, с «вылетом» из программы. Еще хуже, если увлекшись включением/отключением стандартных сообщений разработчик забудет потом в коде программы включить их.

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

Function sDeleteRecord() As Boolean
On Error GoTo Err_
      DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
      DoCmd.DoMenuItem acFormBar, acEditMenu, 6, , acMenuVer70
      sDeleteRecord = True
Exit_:
      Exit Function
Err_:
      ErrNum = Err.Number
      sDeleteRecord = False
      Err.Clear
      Resume Exit_
End Function

      Для ее работы  в глобальном модуле Constants введена переменная Public ErrNum As Long. Через нее передается номер ошибки. Сама же процедура удаления записи выглядит так (для формы «СПРАВОЧНИК страны производители товары»):

Private Sub butDelete_Click()
      sDeleteRecord
      Select Case ErrNum
            Case 2501
                  Err.Clear
            Case 3396
                  MsgBox "Данные нельзя удалять, иначе в таблице [Список товаров] появятся не связанные записи!", vbCritical, "admin"
      End Select
End Sub

      Здесь возможны две ошибки:

  • 2501 – прерывание команды удаления (передумали удалять)
  • 3396 – нарушение целостности данных

      Первую ошибку можно просто игнорировать - Err.Clear, а вот в случае возникновения второй – не помешает вывести соответствующее сообщение, чтобы было понятно, почему нельзя удалять.      Таким образом, можно создавать свои процедуры обработки ошибок выполнения. Чтобы узнать номера ошибок, можно воспользоваться Err.Number. Например, при отладке новой процедуры включить в нее обработчик ошибок:

On Error GoTo Err_

      …..
      …..
      …..

Exit_:
      Exit Sub
Err_:
      MsgBox "Ошибка " & Err.Number & ": " & Err.Description, vbInformation
      Err.Clear ' сброс ошибки
Resume Exit_

Пример по данной статье вы можете скачать здесь, а обсудить статью можно на форуме...

Выпуск 85. Microsoft Access и Framework .NET

Введение
    В этом выпуске рассказывается о применении новой технологии Microsoft Framework .NET и Access. Что это Вам дает.
  • Вы увеличиваете скорость разработки в несколько раз, Конечно при условии того, что Вы знаете как, разрабатывать программы на NET и можете быстро найти нужную функцию. Например, открыть файл, прочитать всю информацию в строку и потом закрыть файл можно одной командой: buffer = File.ReadAllText("test.txt"), для Visual Basic потребовалось бы написать несколько строк кода.
  • Новый редактор VB.NET с улучшенным интерфейсом позволяет Вам быстрее тестировать программы и находить ошибки.
  • Вы сможете создавать красивый интерфейс, шифровать данные, обрабатывать почту, подключать web интерфейс, работать со строками, массивами, хэш информацией и т.п.
  • Вы сможете создавать очень компактные программы, т.к. практически весь код храниться в каталоге NET. Например, данная библиотека с формой имеет размер 0,028 MB, а на Access программа будет иметь значительно больший размер.
  • Можно сказать, что это "окно в Европу", а точнее в Америку.

    P.S. Этот материал для новичков будет "трудноват", но если Вы разрабатывали классы в Access, то проблем в изучении я думаю не будет. Советую материал или ссылку на него сохранить в архиве, т.к., изучая этот материал самостоятельно (без данной статьи), Вы потеряете не менее 1 недели на поиске нужной информации.


1. С чего начать?
  
Сначала научитесь устанавливать Microsoft .NET и регистрировать библиотеку LeadersoftLibrary.dll в среде NET. После разархивации данных в папке Ms Access Вы найдете несколько файлов: "1. Регистрация в Net.bat", "Access и Net.mdb", LeadersoftLibrary.dll, Passwords.txt. Все остальные файлы - дополнительные. В их названии содержится информация о их назначении.
 
а) "1. Регистрация в Net.bat". Запустите этот файл, и библиотека будет зарегистрирована в NET.

б) Изучите строку регистрации:
%windir%\Microsoft.NET\Framework\v2.0.50727\regasm.exe LeadersoftLibrary.dll /tlb:LeadersoftLibrary.tlb /codebase >> status.txt

%windir% - ссылка на c:\windows
LeadersoftLibrary.dll
- основная библиотека для Access. Из нее вызываются функции.
LeadersoftLibrary.tlb
- файл будет создан автоматически. Он используется в VBA в ссылках References ...
/codebase - прописывает в
NET полный путь к библиотеке LeadersoftLibrary.dll
>> status.txt (или
status.doc) - файл будет создан автоматически. В него будет записан статус выполнения команды. Прочтите его после регистрации, если есть слово successfully (успешно), то регистрация прошла правильно.
 

2. Изучение примеров

   
"Access и Net.mdb" - это файл с примерами. После регистрации откройте этот файл и посмотрите как работают примеры с NET. Если что-то не так, то проверьте в ссылках: Tools\References ... наличие LeadersoftLibrary. Примеры следующие.
  • 1 пример - это шифрование данных и сохранение их в файле passwords.txt
  • 2 пример - вызов формы (календарь) из access.
Dim pwd As New password  ' Внешний класс шифрования данных
Dim strFileName As String    ' Файл паролей
Const sKey As String = "Code12345" ' Константа для шифрования


Private Sub Form_Open(Cancel As Integer)
' Полный путь к файлу паролей
strFileName = Application.CurrentProject.Path & "\Passwords.txt"
End Sub

Private Sub butReadPassword_Click()
' Читаем пароль
On Error GoTo 999
With pwd
Me.Password2 = .LeaderSoft_ReadFile(strFileName) ' Чтение пароля
If Me.Password2 <> "" Then
' Расшифровываем
Me.Password1 = .LeaderSoft_Decrypt(Me.Password2, sKey)
Else
' Сохраняем пароль, если файл паролей пустой
Me.Password1 = "New Password"
Me.Password2 = .LeaderSoft_Encrypt(Me.Password1, sKey) ' Шифрование
Call .LeaderSoft_WriteFile(strFileName, Me.Password2) ' Сохранение
End If
End With
Exit Sub
999:
MsgBox Err.Description
Err.Clear
End Sub


' Сохраняем пароль
Private Sub butSavePassword_Click()
On Error GoTo 999
Me.Refresh
With pwd
Me.Password2 = .LeaderSoft_Encrypt(Me.Password1, sKey) ' Шифрование
Call .LeaderSoft_WriteFile(strFileName, Me.Password2) ' Сохранение
End With
Exit Sub
999:
MsgBox Err.Description
Err.Clear
End Sub

' Открываем форму в среде Net
Private Sub butNet_Click()
' 1 вариант
pwd.LeaderSoft_OpenForm
'
' 2 вариант
Dim myDate As New FormCalendar
myDate.Visible = True
myDate.Text = "Еще календарик"
End Sub
 
3. Создание библиотеки NET: LeadersoftLibrary.dll

 
   Для создания библиотеки Вам необходимо будет установить Visual Studio 2005. Откройте файл: LeaderSoftLibrary.vbproj и постройте библиотеку через команду Build LeadersoftLibrary. В результате это будет построена папка Net\Bin\Debug (или Release) найдете нужную информацию: LeaderSoftLibrary.lib - Ваша библиотека, LeaderSoftLibrary.tlb - файл регистрации в VBA, LeaderSoftLibrary.pdb - отладочная информация.
P.S. Ниже написан COM-класс для работы из Access. Примеры взяты из разделов VS и если необходимы пояснения, то их можно прочитать в справке.
 
Imports System.IO
Imports System.Security.Cryptography
Imports System.Windows.Forms
'
' Класс для работы с Microsoft Net из Microsoft Access
'
<ComClass(Password.ClassId, Password.InterfaceId, Password.EventsId)> Public Class Password
Public Const ClassId As String = "98349785-8BE2-4604-848D-F5B103D61715"
Public Const InterfaceId As String = "36613EE9-125F-493d-9968-771E18C2226A"
Public Const EventsId As String = "A036F02F-F87E-4548-A536-7DD7EA8E62B5"

#Region "Управление файлами: http://www.leadersoft.ru"
' Читаем весь файл
Public Function LeaderSoft_ReadFile(ByVal strNameFile As String) As String
Try
LeaderSoft_ReadFile = File.ReadAllText(strNameFile, System.Text.Encoding.UTF8)
Catch ex As Exception
LeaderSoft_ReadFile = ""
MsgBox(ex.Message)
End Try
End Function

' Сохраняем файл
Public Function LeaderSoft_WriteFile(ByVal strNameFile As String, ByVal Buffer As String) As Boolean
Try
File.WriteAllText(strNameFile, Buffer, System.Text.Encoding.UTF8)
LeaderSoft_WriteFile = True
Catch ex As Exception
MsgBox(ex.Message)
LeaderSoft_WriteFile = False
End Try
End Function

#End Region

#Region "Шифрование: http://support.microsoft.com/kb/317535/ru"
' Зашифровка данных

Public Function LeaderSoft_Encrypt(ByVal sIn As String, ByVal sKey As String) As String
Dim DES As New TripleDESCryptoServiceProvider()
Dim hashMD5 As New MD5CryptoServiceProvider()

' Вычисление MD5
DES.Key = hashMD5.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(sKey))
' Устанавливаем режим шифрования.
DES.Mode = CipherMode.ECB
' Создаем блок шифрования
Dim DESEncrypt As ICryptoTransform = DES.CreateEncryptor()
' Получаем байты для шифрования
Dim Buffer As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(sIn)
' Шифруем и возвращаем строку
Return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length))
End Function

' Расшифровка данных
Public Function LeaderSoft_Decrypt(ByVal sOut As String, ByVal sKey As String) As String
Dim DES As New TripleDESCryptoServiceProvider()
Dim hashMD5 As New MD5CryptoServiceProvider()

' Хеширование MD5
DES.Key = hashMD5.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(sKey))
' Устанавливаем режим шифрования.
DES.Mode = CipherMode.ECB
' Создаем блок дешифровки.
Dim DESDecrypt As ICryptoTransform = DES.CreateDecryptor()
Dim Buffer As Byte() = Convert.FromBase64String(sOut)
' Расшифровка данных и возврат строки
Return System.Text.ASCIIEncoding.ASCII.GetString(DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length))
End Function
#End Region

#Region "Управление формами: http://www.leadersoft.ru"
' Вызываем форму
Public Function LeaderSoft_OpenForm() As String
LeaderSoft_OpenForm = ""
' Создаем новую форму
Try
Dim frm As New FormCalendar
frm.Visible = True
frm.Text = "Календарь"

' Перемещаем форму
frm.SetDesktopLocation(30, 50)

' Активация формы
'frm.Activate()

Catch ex As Exception
MsgBox(ex.Message)
End Try

End Function
#End Region


End Class
  ' см. la_NetAccess.zip

Вопрос: Как открыть форму в VB.NET
Ответ.
   Такие команды, как в Access DoCmd.OpenForm в NET отсутствуют. NET - это прежде всего классы, поэтому если что-то делать в NET, то начинать надо с создания класса, используя слово New. Пример
  
Dim frm As New FormCalendar
   frm.Visible = True
Вообще Вы можете и сами создать класс DoCmd и поместить в него нужные функции.
Вопрос: Если в VB.NET функции типа CStr
Ответ.
  Да есть, практически все функции Visual Basic вошли в NET. Вы их может использовать также как и VBA. Пример.
  Dim str As String = CStr("234"). В NET можно объявить и присваивать значение переменной одной командой.

Выпуск 84. Сжатие приложений баз данных

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

Автор. Дмитрий Сонных

Сжатие приложений баз данных.

     Сжатие и архивирование БД я же остановлюсь на сжатии клиентских приложений сделанных как в формате MDB (базы), так и формате ADP (проекты).

Ещё, когда начинал писать на Access 97, возник вопрос, как периодически сжимать базу данных? За время работы она довольно сильно распухала. Решений было несколько, но все они по тем или иным причинам были не оптимальны.

  1. давать пользователю доступ к полному меню Access,  что бы он мог сжимать базу не очень хорошо. Он может изменить какую-нибудь важную установку.
  2. Поставлять с базой утилиту JetCompact тоже не давало желательного эффекта. Утилиту часто теряли, забывали передавать  или устанавливать вместе с базой, При использовании защиты, требовалось задавать дополнительные параметры. Кроме того, многие пользователи были так сказать, «не квалифицированными».
  3. Использование параметров командной строки /compact и epair требовало размещение на рабочем столе дополнительных иконок и иногда сбивало пользователя, если у иконок оказывалось одинаковое изображение. Автоматическое создание иконок на рабочем столе требовало дополнительных знаний в программировании, а в ручную создавать было не всегда возможно. Хотя это и был на мой взгляд наиболее корректный способ обеспечения пользователя инструментом для сжатия базы.
  4. Всевозможные программные ухищрения на основе Access и VBScript. Генерировались всевозможные скрипты для запуска программы на сжатие, программно создавались кнопки, на которые вешались команды на сжатие, создавались специальные программы (mdb) сжималки. Если поикать по форумам то можно найти много следов этой деятельности.

С появлением Access 2000 ситуация несколько улучшилась. В параметрах базы появился флажок «Сжимать при закрытии». Постоянное сжимание базы, хоть и позволяло минимизировать объем базы, но замедляло работу (в и-нете это обсуждалось). Одно ожидание завершения сжатия, особенно когда объем базы перевалил за 10 Мб, может помотать пользователю нервы (а он, естественно, помотает Вам). Вот если бы можно было управлять этим флажком из программы.  Тогда можно дать указание на сжатие файла базы при закрытии, а при открытии базы, сбрасывать установку флажка. Так можно реализовать однократное сжатие базы. Можно написать подпрограмму сжатия базы по расписанию. Осталось только узнать, как это можно сделать. Оказывается сделать это очень просто. Всего две строчки кода
        SetOption "Auto Compact", True ' включить
и
        SetOption "Auto Compact", False ' выключить
Теперь одну строку надо повесить на кнопку включения сжатия файла, а вторую вставить в макрос AutoExec или стартовую форму. И всё готово.

Выпуск 80. Импорт данных в Dotnetnuke

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


О Dotnetnuke
    Технология www.Dotnetnuke.com - это быстрая разработка сайтов, с использованием простых инструментов редактирования. Вам не надо знать программирование для того, чтобы создать профессиональный сайт с великолепным дизайном. Пока не будем говорить в этой рассылке о ее преимуществах, но они, конечно, значительны

Введение в тему  
        Сама база данных сайта Dotnetnuke написана на Microsoft SQL Server и хорошо интегрируется с Microsoft Access. Это и будет показано в этом примере. Суть работы. Имеется много однотипных файлов из конференции на perl в формате htm, которые хорошо читаются браузерами, но из-за большого количества сообщений более 7500 штук, конференция медленно работает. Потребовалось перенести ее в другую базу данных. Этот пример показывает, как можно быстро выполнить импорт данных в Dotnetnuke за несколько минут.
       В качестве вариантов рассматривалась конференция на MySQL (phpBB), но из-за слабой защиты от спама, да и не возможности прямого доступа из Access этот вариант отпал. Лучший выбор пока dotnetnulke, т.к. к конференции прилагается еще и много бесплатных модулей.

Алгоритм решения
Предварительная работа
1. Необходимо определить структуру для сохранения прочитанных сообщений (Автор, Дата, Тема, Сообщение и т.п.)
2. Найти теги, которые будут определять сообщения. Например, <font>Тема: Импорт данных </font>. Тег font определяет внутри htm тему, которую мы потом сохраним в нашей структуре.
3. Найти процедуру в конференции (или создать ее самому), которая будет сохранять в базе данных сообщения. Запустив ее и передав параметры сообщений, мы тем самым сможем быстро заполнить базу данных информацией из файлов htm
4. Найти код на VBA, который в цикле читает все файлы из папки. Это нужно, если файлов много и не надо их вводить по одному в программу для разбора.
5. Найти программы, которые читают содержимое и переименовывают файлы операционной системы. Это пригодится нам, для чтения файла в буфер для анализа. Это лучше, когда весь файл читается, а не анализируется построчно.  После разбора файла его нужно переименовать, чтобы не использовать повторно, т.к. возможны сбои при чтении нескольких  файлов. Например, формат другой, пустые файлы и т.п. И нам придется запускать программу повторно.
Основная работа
 
Далее мы переходим к программированию и создаем управляющую форму и VBA код. Он указан ниже. Его можно, конечно, настроить и на   другой тип htm файлов.


Код на VBA
' Все объекты объявления в форуме
Public Type tpAdds
User As String ' Имя пользователя
Email As String ' Имя почты
AddDate As Date ' Дата записи
Subject As String ' Тело
Body As String ' Текст
Section As String ' Секция
End Type

Public adds() As tpAdds ' Объявления на одну тему
Public tags(10) As String ' Список тегов
Public fso ' Объект файловой системы
Public frmMain As Form ' Форма для вывода данных

' Читаем все файлы html
Public Function funReadHtml(frm As Form, MaxAdds As Long) ' Максимальное число объявлений, 0 - все загружаем
Dim fname As String, html, buf, i As Long
Dim cnn As ADODB.Connection

' Инициализация тегов для html файла
Set frmMain = frm

' Поиск имени
tags(0) = "size=""2"">"
tags(1) = "<br>"

' Поиск Email
tags(2) = "mailto:"
tags(3) = """"

' Поиск даты и времени
tags(4) = "alt=""Email""></a><br><br>"
tags(5) = "<br></font>"

' Поиск темы
tags(6) = "<u>"
tags(7) = "</u>"

' Поиск сообщения
tags(8) = "Сообщение:<br>"
tags(9) = "</font></td>"

' Разбор файлов
With Application.FileSearch
.NewSearch
.LookIn = CurrentProject.Path & "\Data"
.SearchSubFolders = False
.fileName = "*.htm"
If .Execute() > 0 Then
Set cnn = New ADODB.Connection
cnn.CursorLocation = adUseClient
If CurrentProject.IsConnected = True Then
cnn.Open CurrentProject.AccessConnection.ConnectionString
End If
If MaxAdds = 0 Then MaxAdds = .FoundFiles.Count
funPrintStatus " --- Старт: " & Now
For i = 1 To MaxAdds
fname = .FoundFiles(i)
funPrintStatus "Прочитан файл: " & fname & ": " & Now
' Читаем файл
Call fsoReadAllFile(fname, html)
' Разбор файла
If Len(html) > 10 Then
funWriteHtml cnn, html, fGetFileName(fname)
fMoveFile fname, fname & "1"
End If
Next i
funPrintStatus "--- Конец: " & Now
If CurrentProject.IsConnected = True Then
cnn.Close
End If
Else
MsgBox "В каталоге: " & .LookIn & " файлы не найдены! Возможно они были переименованы", vbExclamation, "Администратор"
End If
End With
End Function

' Сохраняем информацию в массиве объявлений
Public Function funWriteHtml(cnn As ADODB.Connection, html, fileName As String)
Dim i As Long, n As Long, p1 As Long, p2 As Long, k As Long, buffer As String, Sec As String

' Поиск границы данных, далее идет форма
'p2 = InStr(1, html, "<!---" & fileName & "--->")
p2 = InStr(1, html, ".htm--->")
buf = Split(Left(html, p2), "<tr>")

' Число строк
n = UBound(buf)
' Название секции
p1 = InStr(1, buf(1), "<b> > </b>")
p1 = InStr(p1 + 10, buf(1), "<b> > ") + 6
p2 = InStr(p1, buf(1), " </b>")
If p2 > p1 Then Sec = Mid(buf(1), p1, p2 - p1)
If InStr(1, Sec, "<") Then Sec = ""

If n > 2 Then
ReDim adds(n - 3) ' Пропускаем 3 строки сверху
For i = 3 To n
p1 = 1 ' Начало поиска
adds(i - 3).Section = Sec
For j = 0 To 4
' Начало поиска
k = InStr(p1, buf(i), tags(j * 2))
' Левый тег найден
If k > 0 Then
p1 = k + Len(tags(j * 2))
p2 = InStr(p1, buf(i), tags(j * 2 + 1))
' Результат поиска правого тега - положительный
If p2 > p1 Then
buffer = Mid(buf(i), p1, p2 - p1)
Select Case j
Case 0: adds(i - 3).User = buffer
Case 1: adds(i - 3).Email = buffer
Case 2: adds(i - 3).AddDate = CDate(Replace(buffer, "<br>", " "))
Case 3: adds(i - 3).Subject = buffer
Case 4: adds(i - 3).Body = buffer
End Select
' Новая позиция поиска
p1 = p2 + Len(tags(j * 2 + 1))
End If
End If
Next
Next
' Добавляем данные в конференцию
dnn_Forum_PostAdd cnn, fileName
End If
End Function

' Получаем имя файла
Public Function fGetFileName(strPath As String) As String
Dim fs
On Error GoTo 999
Set fs = CreateObject("Scripting.FileSystemObject")
fGetFileName = fs.GetFileName(strPath)
Set fs = Nothing

Exit Function
999:
MsgBox Err.Description, vbCritical, strPath
Err.Clear
End Function

Public Function fMoveFile(strPath1 As String, strPath2 As String) As Boolean
Dim fs
On Error GoTo 999
Set fs = CreateObject("Scripting.FileSystemObject")
fs.MoveFile strPath1, strPath2
Set fs = Nothing
Exit Function
999:
'MsgBox Err.Description, vbCritical, strPath
Err.Clear
fDeleteFile = False
End Function


' Загрузка всего файла в буфер
Public Function fsoReadAllFile(fname, buffer)
Dim f
' Создаем файловую систему
fsoCreateFileSystem

' Читаем весь файл
If (fso.FileExists(fname)) Then
Set f = fso.OpenTextFile(fname, 1, -1)
buffer = f.ReadAll
f.Close
fsoReadAllFile = True
Else
fsoReadAllFile = False
End If
End Function


Public Function fsoCreateFileSystem()
If IsEmpty(fso) Then
Set fso = CreateObject("Scripting.FileSystemObject")
End If
End Function

' Печать информации
Private Sub funPrintStatus(txt As String)
On Error GoTo 999
If frmMain.txtStatus.ListCount > 500 Then
frmMain.txtStatus.RowSource = ""
End If

frmMain.txtStatus.RowSource = txt & ";" & frmMain.txtStatus.RowSource
DoEvents
frmMain.Repaint
Exit Sub
999:
frmMain.txtStatus.RowSource = ""
End Sub

'
' Добавляем объявления в конференцию Dotnetnuke
' Работает только при подключении к серверу с процедурой: Forum_PostAdd
'
Private Function dnn_Forum_PostAdd(cnn As ADODB.Connection, fileName As String) As Boolean
' Вспомогательные параметры
Dim cmd As New ADODB.Command, i As Long, PostID As Long, cnt As Long
On Error GoTo 999
If CurrentProject.IsConnected = False Then
MsgBox "Необходимо adp проект связать с базой данных dotnetnuke", vbCritical, "Admin"
Exit Function
End If
PostID = 0
Set cmd.ActiveConnection = cnn
cmd.CommandText = "dnn_Forum_PostAdd" ' По умолчанию процедура добавления: Forum_PostAdd
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Refresh ' Запрос параметров процедуры
Dim rst As New ADODB.Recordset
For i = 0 To UBound(adds)
' Инициализируем данные
cmd.Parameters("@ParentPostID") = PostID
cmd.Parameters("@ForumID") = 1 ' Access Forum
cmd.Parameters("@UserID") = 19
cmd.Parameters("@RemoteAddr") = ""
cmd.Parameters("@Notify") = 0
cmd.Parameters("@Subject") = adds(i).Subject
cmd.Parameters("@Body") = adds(i).Body & "P.S. " & adds(i).Section & "<br>Автор: <a href=""mailto:" & adds(i).Email & """>" & adds(i).User & "</a> от " & adds(i).AddDate & " <a href=""http://www.leadersoft.ru/rusboard/data/" & fileName & """>Источник ...</a>"
cmd.Parameters("@IsPinned") = 0
cmd.Parameters("@PinnedDate") = adds(i).AddDate
cmd.Parameters("@IsClosed") = 0
cmd.Parameters("@Image") = ""
cmd.Parameters("@mediaURL") = ""
cmd.Parameters("@mediaNAV") = ""
cmd.Parameters("@ObjectTypeCode") = 0
cmd.Parameters("@ObjectID") = 0
cmd.Parameters("@FileAttachmentURL") = ""
cmd.Execute RecordsAffected:=cnt, options:=adExecuteNoRecords
If cnt <> 0 And i = 0 Then
PostID = DMax("PostID", "dnn_Forum_Posts") ' Запрос последнего добавленного сообщения
End If
Next
Exit Function
999:
MsgBox Err.Description, vbCritical, "Администратор"
End Function

Выпуск 83. Автоматизация. Вывод данных в Word

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

Автор: Парусников Алексей

Автоматизация. Вывод данных в Word.

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

  • требуется сформировать договор, который, как правило, представляет собой довольно длинный текстовый документ, в который нужно вставить несколько чисел или строк – например даты.
  • нужно обеспечить возможность ручного редактирования текста документа. Например, существует стандартный шаблон документа, который пользователь должен иметь возможность редактировать. Если использовать отчет Access, то придется открывать пользователю доступ к исходному коду.
  • документ должен быть сохранен в виде текстового файла (отчет Access может быть только напечатан). Иногда бывают и такие условия.

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

      Вообще, каждый документ Microsoft Word основан на шаблоне. Шаблон определяет основную структуру документа и содержит настройки документа, такие как элементы автотекста, шрифты, назначенные сочетания клавиш, макросы, меню, параметры страницы, форматирование и стили. В нашем же случае, необходимо просто создать макет отчета подобно тому как это делается в Access. Для этого создаем обычный документ Word, затем в меню Файл – Сохранить как  выбираем тип файла – Шаблон документа. В результате получим документ Word с расширением .dot – шаблон.

      Для редактирования шаблона лучше его открывать не двойным щелчком, как обычный документ, а например, через контекстное меню: правой кнопкой – и выбрать пункт открыть. В противном случае при попытке сохранения придется повторно задавать формат документа – шаблон (.dot), иначе он будет сохранен как обычный документ Word (.doc).

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

      А теперь собственно о технологии вставки текста в нужное место. Чтобы вставить текст, сначала нужно определить место, куда он должен вставляться. В данном примере это делается при помощи «Закладок» (смотрим в меню документа Word: Вставка – Закладка).

      Закладка — это элемент документа, которому присвоено уникальное имя. Это имя можно использовать для последующих ссылок. Например, можно использовать закладку для определения текста, который необходимо проверить позже. Чтобы в следующий раз не искать данный текст во всем документе, можно перейти к нему с помощью диалогового окна Закладка.

В нашем случае закладками являются элементы шаблона, выделенные курсивом (смотрим в папку Dot). Создаются они очень просто:

  • Выделите элемент, которому следует назначить закладку – например курсивный текст Заказчик
  • В меню Вставка выберите команду Закладка
  • В поле Имя закладки введите или выберите нужное имя – в данном случае вводим имя «Заказчик». Имя закладки должно начинаться с буквы, в нем могут использоваться цифры, но не должно быть пробелов. Если потребуется разделить слова в имени закладки, можно использовать знак подчеркивания, например:  Главный_заказчик.
  • Нажмите кнопку Добавить.

      В итоге получили закладку с именем «Заказчик». В принципе, можно было просто установить курсор в нужное место и вышесказанным образом создать закладку. Но тогда для просмотра, где какая закладка установлена в документе нужно будет через меню Вставка – Закладка выбрать имя закладки и нажать кнопку Перейти. Это неудобно, проще и нагляднее создать одноименный текст в документе.

      Теперь осталось создать функцию, которая бы открывала созданный шаблон Word, вставляла бы туда вместо закладок нужный текст и сохраняла созданный документ под заданным именем. В прошлой статье уже рассказывалось о способах открытия документов Office. Осталось только выяснить, как обратиться к закладке. Делается это при помощи свойства документа Bookmarks.Item Например:

Bookmarks.Item("Заказчик").Range.Text = Nz(Заказчик, "")

      Здесь идет обращение к закладке под именем Заказчик и при помощи ее свойства Text ей присваивается нужное значение – в данном случае содержимое одноименного поля  на форме. На случай, если в поле нет данных, применена функция Nz(Значение, Значение если Null).

      Документ создается под именем инициалов заказчика, поэтому данное поле не должно быть пустым. Это реализовано при помощи свойства поля (см. конструктор таблиц) «Обязательное поле - Да». Кроме того, в приведенном примере так же реализована процедура поиска ранее созданного документа при помощи стандартной функции Dir. Если документ не найден, то создается новый документ Word на основе шаблона

Set app = New Word.Application
app.Visible = True
app.Documents.Add strPathDot

      если же такой документ существует, то выводится соответствующее сообщение: «Документ с таким именем ранее уже был создан. Заменить его?» При выборе «Да» создается новый документ взамен старого, при выборе «Нет» открывается старый документ

Set app = CreateObject("Word.Application")
With app
      .Visible = True
      .Documents.Open strPathWord
End With