Архив за месяц: Апрель 2014

Без рубрики

OpenOfficeBase + HSQL + H2 (SQL)

В качестве встроенного движка ООВ исползует втроенную базу данных Н. Ее легко можно запускать и в серверном варианте. Впрочем, куда более перспективно использовать похожую базу данных Н2 (фактически от того же разработчика). Чем мне понравился Н2, так это возможностью шифорвания файла базы данных.Фактически это единственный вриант бесплатной и продвинутой БД с поддержкой шифрования. Ключ задается в строке подключения как первая часть пароля (и далее через пробел собственно пароль юсера). Не такое уж удобное решение.
Без рубрики

OpenOfficeBase + HSQL + H2 (SQL)

В качестве встроенного движка ООВ исползует втроенную базу данных Н. Ее легко можно запускать и в серверном варианте. Впрочем, куда более перспективно использовать похожую базу данных Н2 (фактически от того же разработчика). Чем мне понравился Н2, так это возможностью шифорвания файла базы данных.Фактически это единственный вриант бесплатной и продвинутой БД с поддержкой шифрования. Ключ задается в строке подключения как первая часть пароля (и далее через пробел собственно пароль юсера). Не такое уж удобное решение.

Git & Unicode

Начиная с версии V1.7.10 Git for Windows поддерживает кодировку Unicode.

Имена файлов и каталогов, выполненные кирилицей, в Git for Windows могут отображаться, например так:


Чтобы это исправить, следует в консоли Git установить используемым шрифт TrueType, например Lucida Console или Consolas:


И произвести ряд изменений в настройках Git, посредством запуска команд:

git config --global core.quotepath off
git config --global --unset i18n.logoutputencoding
git config --global --unset i18n.commitencoding
git config --global --unset svn.pathnameencoding

Результат выглядит следующим образом:



Источник информации здесь.

Англоязычный вариант книги Pro Git здесь (pdf формат).
Русский перевод книги Pro Git здесь (pdf формат).

P.S. Если вам потребовалось в Git for Windows для операции git commit назначить иной текстовый редактор, путь к exe файлу которого содержит пробелы - в этом случае, при указании полного пути к exe файлу, следует внутри кавычек одного типа, дополнительно указывать кавычки другого типа. Т.е. либо одинарные кавычки упаковывать в двойные, либо наоборот - двойные кавычки упаковывать в одинарные. В общем, в подобных случаях следует использовать любой из следующих вариантов:

git config --global core.editor "'C:Program FilesNotepad++notepad++.exe'"
git config --global core.editor '"C:Program FilesNotepad++notepad++.exe"'


OpenOfficeBase + Basic — обещанное продолжение.

После почти двухлетнего перерыва, связанного со сменой профессональных интересов и поиском красивых решений - продолжаю повествование. Что же поменялось?

Во-первых, я стал более ориентироваться на использование в качестве движка OpenOfficrBase (not OpenOfficeWriter). Это произошло в связи с тем, что 3-я версия офиса поддерживает библиотеки уроня файла базы данных, которые могут удобно распрастраняться внутри файла .odb.

Во-вторых, я перешел на использование соединения JDBC, так как "родные" офисные соединения, к сожалению, не всегда поддерживают возможности JDBC 3...4.

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

Теперь немного кода.

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

Sub FromBaseToDialog(oForm, oDialog)
If oForm.IsNew Or oForm.IsAfterLast() Or oForm.IsBeforeFirst() Then
Exit Sub
End If
Dim I
Dim sName As String
For I = 0 To Ubound(oDialog.Model.ElementNames)
sName = oDialog.Model.ElementNames(I)
If Mid(sName, 1, 1) <> "_" And Mid(sName, 1, 5) <> "Label" Then
ODialog.GetControl(sName).SetText(oForm.Columns.GetByName(sName).String)
End If
If Mid(sName, 1, 6) = "_date_" Then
DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
If Mid(sName, 1, 7) = "_combo_" Then
'xRay oForm.Columns.GetByName(Mid(sName, 8))
If oForm.Columns.GetByName(Mid(sName, 8)).String <> "" Then
InitComboBox(oDialog, sName, oForm.Columns.GetByName(Mid(sName, 8)).String)
End If
End If


Next I
End Sub

Sub FromDialogToBase(oDialog, oForm)
Dim I
Dim sName As String
For I = 0 To Ubound(oDialog.Model.ElementNames)
sName = oDialog.Model.ElementNames(I)
If Mid(sName, 1, 1) <> "_" And Mid(sName, 1, 5) <> "Label" Then
If Mid(sName,1,4) = "date" Then
oForm.Columns.GetByName(sName).UpdateString(ctl.util.Replace(Trim(oDialog.GetControl(sName).GetText()), ",", "."))
Else
oForm.Columns.GetByName(sName).UpdateString(Trim(oDialog.GetControl(sName).GetText()))
End If
End If
If Mid(sName, 1, 6) = "_date_" Then
DateFromControlToBase(ODialog.GetControl(sName), oForm.Columns.GetByName(Mid(sName, 7)))
' DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
If Mid(sName, 1, 7) = "_combo_" Then
oForm.Columns.GetByName(Mid(sName, 8)).UpdateString(ODialog.GetControl(sName).GetModel.Tag)
' DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
Next I
End Sub

Как видно, есть специальные имена, начинающиеся с знака подчеркивания. Они подойдут для всяких меток, которые не должны обрабатываться. И еще пока что два обрабатываемых имени _date_ и _combo_, которые обрабатываются специальным образом. О списках  (комбобоксах) ма поговорим в следующий раз, а о датах можно поговорить сейчас. OpenOffice удобно обрабатывает даты вводом через календарь, но что касается перевода БД в строку, присваивания строки элементу и обратно - то тут царит полнй хаос. Для PosgreSQL я использую вспомогательные функции:

Function DateToControl(dt) As Long
DateToControl = dt.YEAR*10000 + dt.MONTH*100 + dt.DAY
End Function

Sub DateFromBaseToControl(field, ctl)
If DateToControl(field.DATE) > 0 Then
ctl.SetDate(DateToControl(field.DATE)
Else
ctl.SetText("")
End If
End Sub

Function DateFromControl(dt As Long) As Object
Dim oDt As New com.sun.star.util.Date
Dim NewDate As String
NewDate = dt
If dt > 0 Then
oDt.YEAR = Mid(NewDate,1,4)
oDt.MONTH = Mid(NewDate,5,2)
oDt.DAY = Mid(NewDate,7,2)
End If
DateFromControl = oDt
End Function

Sub DateFromControlToBase(ctl, field)
if ctl.GetDate() <> 0 Then
field.UpdateDate(DateFromControl(ctl.GetDate()))
else
field.UpdateNull()
End If
End Sub

Ну вот собственно и все.

Теперь по кнопке вызываем диалог:

Sub Dogovor_Edit(Event)
Dim oDialog As Object
Dim f_dogovor As Object
f_dogovor = Thiscomponent.DrawPage.Forms.GetByName("f_dogovor")
oDialog = GetDialog("ctl", "dogovor")
If oDialog.Execute() = 1 Then
If Event.Source.Model.Tag = "new" Then
f_dogovor.MoveToInsertRow()
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.InsertRow()
Else
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.UpdateRow()
EndIf
Else
End If
End Sub



Пока.

OpenOfficeBase + Basic — обещанное продолжение.

После почти двухлетнего перерыва, связанного со сменой профессональных интересов и поиском красивых решений - продолжаю повествование. Что же поменялось?

Во-первых, я стал более ориентироваться на использование в качестве движка OpenOfficrBase (not OpenOfficeWriter). Это произошло в связи с тем, что 3-я версия офиса поддерживает библиотеки уроня файла базы данных, которые могут удобно распрастраняться внутри файла .odb.

Во-вторых, я перешел на использование соединения JDBC, так как "родные" офисные соединения, к сожалению, не всегда поддерживают возможности JDBC 3...4.

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

Теперь немного кода.

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

Sub FromBaseToDialog(oForm, oDialog)
If oForm.IsNew Or oForm.IsAfterLast() Or oForm.IsBeforeFirst() Then
Exit Sub
End If
Dim I
Dim sName As String
For I = 0 To Ubound(oDialog.Model.ElementNames)
sName = oDialog.Model.ElementNames(I)
If Mid(sName, 1, 1) <> "_" And Mid(sName, 1, 5) <> "Label" Then
ODialog.GetControl(sName).SetText(oForm.Columns.GetByName(sName).String)
End If
If Mid(sName, 1, 6) = "_date_" Then
DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
If Mid(sName, 1, 7) = "_combo_" Then
'xRay oForm.Columns.GetByName(Mid(sName, 8))
If oForm.Columns.GetByName(Mid(sName, 8)).String <> "" Then
InitComboBox(oDialog, sName, oForm.Columns.GetByName(Mid(sName, 8)).String)
End If
End If


Next I
End Sub

Sub FromDialogToBase(oDialog, oForm)
Dim I
Dim sName As String
For I = 0 To Ubound(oDialog.Model.ElementNames)
sName = oDialog.Model.ElementNames(I)
If Mid(sName, 1, 1) <> "_" And Mid(sName, 1, 5) <> "Label" Then
If Mid(sName,1,4) = "date" Then
oForm.Columns.GetByName(sName).UpdateString(ctl.util.Replace(Trim(oDialog.GetControl(sName).GetText()), ",", "."))
Else
oForm.Columns.GetByName(sName).UpdateString(Trim(oDialog.GetControl(sName).GetText()))
End If
End If
If Mid(sName, 1, 6) = "_date_" Then
DateFromControlToBase(ODialog.GetControl(sName), oForm.Columns.GetByName(Mid(sName, 7)))
' DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
If Mid(sName, 1, 7) = "_combo_" Then
oForm.Columns.GetByName(Mid(sName, 8)).UpdateString(ODialog.GetControl(sName).GetModel.Tag)
' DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
Next I
End Sub

Как видно, есть специальные имена, начинающиеся с знака подчеркивания. Они подойдут для всяких меток, которые не должны обрабатываться. И еще пока что два обрабатываемых имени _date_ и _combo_, которые обрабатываются специальным образом. О списках  (комбобоксах) ма поговорим в следующий раз, а о датах можно поговорить сейчас. OpenOffice удобно обрабатывает даты вводом через календарь, но что касается перевода БД в строку, присваивания строки элементу и обратно - то тут царит полнй хаос. Для PosgreSQL я использую вспомогательные функции:

Function DateToControl(dt) As Long
DateToControl = dt.YEAR*10000 + dt.MONTH*100 + dt.DAY
End Function

Sub DateFromBaseToControl(field, ctl)
If DateToControl(field.DATE) > 0 Then
ctl.SetDate(DateToControl(field.DATE)
Else
ctl.SetText("")
End If
End Sub

Function DateFromControl(dt As Long) As Object
Dim oDt As New com.sun.star.util.Date
Dim NewDate As String
NewDate = dt
If dt > 0 Then
oDt.YEAR = Mid(NewDate,1,4)
oDt.MONTH = Mid(NewDate,5,2)
oDt.DAY = Mid(NewDate,7,2)
End If
DateFromControl = oDt
End Function

Sub DateFromControlToBase(ctl, field)
if ctl.GetDate() <> 0 Then
field.UpdateDate(DateFromControl(ctl.GetDate()))
else
field.UpdateNull()
End If
End Sub

Ну вот собственно и все.

Теперь по кнопке вызываем диалог:

Sub Dogovor_Edit(Event)
Dim oDialog As Object
Dim f_dogovor As Object
f_dogovor = Thiscomponent.DrawPage.Forms.GetByName("f_dogovor")
oDialog = GetDialog("ctl", "dogovor")
If oDialog.Execute() = 1 Then
If Event.Source.Model.Tag = "new" Then
f_dogovor.MoveToInsertRow()
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.InsertRow()
Else
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.UpdateRow()
EndIf
Else
End If
End Sub



Пока.

О совместимости версий .NET плагинов, AutoCAD, .NET Framework и MS Visual Studio

Маленькая шпаргалка на тему совместимости версий .NET плагинов, AutoCAD, .NET Framework и MS Visual Studio. Вообще, Visual Studio можно использовать любую: главное, чтобы она поддерживала возможность писать код под нужную нам версию .NET Framework. Разные версии AutoCAD могут использовать разные версии .NET Framework и плагины, использующие эти платформы. Кроме того, некоторые управляемые плагины можно использовать в разных версиях AutoCAD без необходимости их перекомпиляции.

[R17.2] AutoCAD 2009: .NET 3.0, 3.5; Visual Studio 2005 и более новые.
[R18.0] AutoCAD 2010: .NET 3.5; Visual Studio 2005 и более новые.
[R18.1] AutoCAD 2011: .NET 3.5, 4.0, 4.5, 4.5.1 (см. примечание 1); Visual Studio 2005 и более новые.
[R18.2] AutoCAD 2012: .NET 4.0, 4.5, 4.5.1 (см. примечание 2); Visual Studio 2010 и более новые.
[R19.0] AutoCAD 2013: .NET 4.0, 4.5, 4.5.1 (см. примечание 2); Visual Studio 2010 и более новые.
[R19.1] AutoCAD 2014: .NET 4.0, 4.5, 4.5.1 (см. примечание 2); Visual Studio 2010 и более новые.
[R20.0] AutoCAD 2015: .NET 4.5, 4.5.1 (см. примечание 2); Visual Studio 2012 и более новые.

Особым образом хочется выделить AutoCAD 2010 и 2011. Официально компанией Autodesk заявлено, что эти версии требуют для своей работы Microsoft Visual Studio 2008 with Service Pack 1 и Microsoft .NET Framework 3.5 with Service Pack 1. Однако практика показывает, что если у программиста под рукой окажется только Visual Studio 2005 и AutoCAD 2011, то написать плагин он сможет. Но в виду того, что в Visual Studio 2005 нет возможности указать целевую версию платформы .NET, этот плагин будет компилироваться с использованием .NET 2.0. Соответственно, при написании плагина AutoCAD, программист будет ограничен рамками платформы .NET 2.0. Например, он не сможет использовать технологии LINQ и WPF.

Для примера, в Visual Studio 2005 автор написал и скомпилировал плагин для AutoCAD 2011, который успешно запустился в обозначенной версии AutoCAD:

   1:  using System;
   2:  using cad = Autodesk.AutoCAD.ApplicationServices
   3:  .Application;
   4:  using Rt = Autodesk.AutoCAD.Runtime;
   5:   
   6:  namespace acad_2011{
   7:      public class Class1 {
   8:          [Rt.CommandMethod("test", Rt.CommandFlags.Modal)]
   9:          public void Test(){
  10:              cad.DocumentManager.MdiActiveDocument
  11:                  .Editor.WriteMessage(
  12:                  "MS VS 2005: Hello, AutoCAD 2011!n");
  13:          }
  14:      }
  15:  }

В подкаталоге inс установленного ObjectARX SDK, управляемые сборки появились лишь начиная с AutoCAD 2011. .NET плагины, использующие сборки AutoCAD только из этого каталога, можно без опасений компилировать как AnyCPU. В иных случаях нужно быть осторожным. Начиная с AutoCAD 2013 в обозначенном подкаталоге появился файл AcCoreMgd.dll. В новый файл было вынесено часть функционала из файла AcDbMgd.dll и часть из файла AcMgd.dll.

Небольшая переведённая мною на русский язык цитата, автором которой является Scott McFarlane [CP2654]:
В последние несколько лет компания Autodesk работала над разделением бизнес логики AutoCAD от логики взаимодействия с GUI. Такое разделение позволяет иметь единую кодовую базу, не зависящую от конкретной операционной системы (Windows, MacOS). Это разделение было названо "большим разделением" (The Big Split). Указанная работа была завершена в AutoCAD 2013 и теперь мы имеем трёх уровневую архитектуру, как показано ниже:




Важно понимать, что каждый уровень зависит от ниже расположенных уровней и не зависит от уровней расположенных выше. Два нижних уровня представляют собой механизм ядра AutoCAD (AutoCAD Core Engine). В виду высокой скорости своего запуска, помимо использования в пакетной обработке чертежей, приложение AcCoreConsole так же хорошо подходит и для проведения автоматического тестирования кода.

Теперь программный код рекомендуется писать разделяя его зависящую от AutoCAD API часть от той части, которая не зависит от AutoCAD API. Затем, часть кода, зависящую от AutiCAD API в свою очередь рекомендуется делить на две части: на ту, которая зависит лишь от базового уровня (библиотеки acdbmgd.dll и accoremgd.dll) и на ту, которая зависит от UI (acmgd.dll).

Начиная с AutoCAD 2013 SP1 был внедрён механизм безопасности загрузки в AutoCAD сторонних программных библиотек (подробнее здесь). Начиная с AutoCAD 2014, на вкладке Files диалогового окна Options присутствует ветка Trusted Locations.

Если вы написали управляемый плагин под одну версию AutoCAD, то сможете использовать его и для другой версии AutoCAD, в случае выполнения следующих условий:
1. Обе версии AutoCAD могут использовать ту версию .NET Framework, которая применялась при написании плагина (см. примечание 1).
2. К вашему плагину AutoCAD подключены библиотеки, присутствующие в обоих версиях AutoCAD.
3. Ваш плагин использует только ту часть API, которая присутствует в обоих рассматриваемых версиях AutoCAD.
4. Если управляемый плагин скомпилирован с опцией x86 или x64 (например, по причине использования Interop в вашем коде), то и целевые версии AutoCAD должны иметь ту же самую разрядность, что и плагин.

ВНИМАНИЕ!
Даже если выполнены все обозначенные выше условия, всё равно следует обязательно произвести тестирование (желательно с использованием Gallio) вашего плагина на полную его совместимость с иными, интересующими вас версиями AutoCAD (т.е. загрузить плагин и проверить его работоспособность).

Примечание 1:
В AutoCAD 2011 конфигурационный файл acad.exe.config содержит закомментированные XML элементы, указывающие целевую версию .NET Framework:

   1:  <!--<startup useLegacyV2RuntimeActivationPolicy="true">
   2:  <supportedRuntime version="v4.0"/>
   3:  </startup>-->

В этом состоянии AutoCAD 2011 использует .NET 3.5, но если указанные выше XML элементы раскомментировать, то AutoCAD 2011 будет использовать наиболее новую версию .NET из тех которые приложение сможет найти и использовать. Применительно к AutoCAD 2011 это будут версии .NET 4.0, 4.5 и 4.5.1.

Примечание 2:
В отличие от AutoCAD 2011, в конфигурационных файлах AutoCAD 2012-2015 обозначенные в "Примечании 1" XML элементы по умолчанию раскомментированы.

Примечание 3:
Если вместо acad.exe используется accoreconsole.exe, то его конфигурационный файл, соответственно, следует искать под именем accoreconsole.exe.config.