четверг, 10 апреля 2014 г.

MSSQL: Функция для транслита

Попытался тут давеча использовать SOUNDEX и DIFFERENCE для поиска похожих фамилий. Безуспешно - выяснилось, что эти функции с кириллицей не работают. Возникла идея транслитерировать фамилии и уже затем скармливать их этим функциям. Эксперимент показал, что всё равно получается не очень хорошо, так что идея умерла. А функция транслитерации (по стандарту ГОСТ Р 52535.1-2006) осталась, вот:
CREATE FUNCTION TranslitString(@string varchar(256)) RETURNS varchar(256)
AS BEGIN

DECLARE @return varchar(256)

SET @return = UPPER(@string)
SET @return = REPLACE(@return, 'АЙ', 'AY')
SET @return = REPLACE(@return, 'ЕЙ', 'EY')
SET @return = REPLACE(@return, 'ИЙ', 'IY')
SET @return = REPLACE(@return, 'ОЙ', 'OY')
SET @return = REPLACE(@return, 'УЙ', 'UY')
SET @return = REPLACE(@return, 'ЫЙ', 'Y')
SET @return = REPLACE(@return, 'ЭЙ', 'EY')
SET @return = REPLACE(@return, 'ЮЙ', 'YUY')
SET @return = REPLACE(@return, 'ЯЙ', 'YAY')
SET @return = REPLACE(@return, 'А', 'A')
SET @return = REPLACE(@return, 'Б', 'B')
SET @return = REPLACE(@return, 'В', 'V')
SET @return = REPLACE(@return, 'Г', 'G')
SET @return = REPLACE(@return, 'Д', 'D')
SET @return = REPLACE(@return, 'Е', 'E')
SET @return = REPLACE(@return, 'Ё', 'E')
SET @return = REPLACE(@return, 'Ж', 'ZH')
SET @return = REPLACE(@return, 'З', 'Z')
SET @return = REPLACE(@return, 'И', 'I')
SET @return = REPLACE(@return, 'Й', 'I')
SET @return = REPLACE(@return, 'К', 'K')
SET @return = REPLACE(@return, 'Л', 'L')
SET @return = REPLACE(@return, 'М', 'M')
SET @return = REPLACE(@return, 'Н', 'N')
SET @return = REPLACE(@return, 'О', 'O')
SET @return = REPLACE(@return, 'П', 'P')
SET @return = REPLACE(@return, 'Р', 'R')
SET @return = REPLACE(@return, 'С', 'S')
SET @return = REPLACE(@return, 'Т', 'T')
SET @return = REPLACE(@return, 'У', 'U')
SET @return = REPLACE(@return, 'Ф', 'F')
SET @return = REPLACE(@return, 'Х', 'KH')
SET @return = REPLACE(@return, 'Ц', 'TC')
SET @return = REPLACE(@return, 'Ч', 'CH')
SET @return = REPLACE(@return, 'Ш', 'SH')
SET @return = REPLACE(@return, 'Щ', 'SHCH')
SET @return = REPLACE(@return, 'Ы', 'Y')
SET @return = REPLACE(@return, 'Э', 'E')
SET @return = REPLACE(@return, 'Ю', 'IU')
SET @return = REPLACE(@return, 'Я', 'IA')
SET @return = REPLACE(@return, 'Ь', '')
SET @return = REPLACE(@return, 'Ъ', '')

RETURN @return

END

четверг, 27 марта 2014 г.

Windows: сообщение stdole32.tlb при запуске MS Excel 2007

Почему-то при запуске MS Excel 2007 каждый раз выдаётся уведомление с очень информативным текстом "stdole32.tlb", после чего запускается программа установки офиса, что-то там делает и только после этого позволяет работать с екселем. Не знаю, то ли ексель радуется, что нашёл stdole32.tlb, то ли печалится, что наоборот, нет доступа к этому критически важному файлу.

В интернете есть несколько советов по исправлению этого поведения, см., например, вот. Мне же помог такой вариант. Вкратце:

1. Деинсталлируем офис.

2. Запускаем два FixIt-а:
Для деинсталляции MSOffice2007
http://support.microsoft.com/kb/928218
Для деинсталляции MSOffice2003
http://support.microsoft.com/kb/2639197

3. Запускаем еще одну утилиту - вроде как помощник для установки и удаления программ:
http://support.microsoft.com/mats/Program_Install_and_Uninstall
(не знаю, правда, зачем, по-моему, она всё равно ничего полезного не сделала)

4. Инсталлируем офис по-новой.

четверг, 13 марта 2014 г.

Windows: как в UAC добавить исключение

Сам не проверял, но попалась интересная статья. Вкратце:

1. Устанавливаем Microsoft Application Compatibility Toolkit 5.6

2. Запускаем Compatibility Administrator от имени администратора.

3. Нажимаем кнопку Fix, следуем указаниям мастера, в результате получаем базу данных с параметрами совместимосте, сохраняем её, затем через меню File->Install эту базу данных устанавливаем.

В результате обработанное таким образом приложение должно выполняться из-под учетной записи пользователя без лишних запросов со стороны UAC.

Надо будет попробовать.

среда, 12 марта 2014 г.

Ubuntu: Печать страниц в альбомной ориентации в LibreOffice

Оказывается, это не так тривиально. Помогло следующее:
Внутри LibreOffice в меню Tools, пункт Options, раздел LibreOffice, пункт Print снять галочку опции "PDF as Standard Print Job Format".

понедельник, 17 февраля 2014 г.

Python: Числовые ребусы

Программка для разгадывания числовых ребусов. Методом грубой силы (т.е. простым перебором).

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys

#equation = u'удар+удар==драка'
#equation = u'кошка+кошка+кошка==собака'
#equation = u'кто+умён+тот==силён'
#equation = u'где*где-всюду==везде'
equation = u'масло+ноль==омлет'

def replace_all(text, srch, repl):
    for i in range(0, len(srch)):
        text = text.replace(srch[i], repl[i])
    return text

letters = []

for l in equation:
    if l not in ('+', '=', '-', '*'):
        if l not in letters:
            letters.append(l)

tops, counters = [], []
for i in range(0, len(letters)):
    tops.append(10 - i)
    counters.append(0)

canExit = False
while(not(canExit)):

    numbers = ['0','1','2','3','4','5','6','7','8','9']
    substs = []
    for i in range(0, len(tops)):
        substs.append(numbers[counters[i]])
        del numbers[counters[i]]

    text = replace_all(equation, letters, substs)
    try:
        if eval( text ):
            print text
    except:
        None

    N = 0
    inc = 1
    while (N < len(counters) and inc > 0):
        counters[N] += inc
        inc = 0
        if (counters[N] == tops[N]):
            counters[N] = 0
            inc = 1
            N += 1

    canExit = True
    for i in range(0, len(tops)):
        canExit &= (counters[i] == tops[i]-1)

Windows: Создаём MSI

Возникла тут небольшая задачка.

Есть некая программа. Разработчик этой программы периодически присылает её обновления. Эти обновления имеют хитрое расширение AAA.upg и устанавливаются с помощью специальной утилиты UUU.exe

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

Получается, что остаётся два варианта установки обновлений. Первый: на каждом компьютере установить утилиту UUU.exe и настроить с ней ассоциацию файлов *.upg. Затем рассылать, скажем, по почте очередные обновления, и пусть пользователи их запускают двойным кликом. Этот способ имеет свои недостатки. Например, попытка этой утилиты с пользовательскими правами что-нибудь записать в системные каталоги будет заведомо неудачной.

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

Итак, задача. Есть два файла, UUU.exe и AAA.upg. Нужно сделать инсталляционный пакет MMM.msi, который бы разархивировал эти два файла и затем выполнял команду "UUU.exe AAA.upg".

В качестве инструментов для решения этой задачи используются:
1. Архиватор 7-zip и его расширения для создания SFX-архивов (7-zip extra)
2. Конвертер исполняемых файлов в инсталляционные пакеты: http://www.exetomsi.com/freeware.php

Решение такое.

1. Создаём архив ZZZ.7z, содержащий два файла, UUU.exe и AAA.upg.

2. Из пакета 7-zip extra вытаскиваем файл 7zsd.sfx и кладём его рядом с архивом ZZZ.7z

3. Создаём файл config.txt с таким содержимым:
;!@Install@!UTF-8!
RunProgram="UUU.exe AAA.upg"
GUIMode="2"
;!@InstallEnd@!

4. Собираем самораспаковывающийся архив командой:
COPY /b 7zsd.sfx + config.txt + ZZZ.7z MMM.exe

5. Конвертируем получившийся исполняемый файл MMM.exe в MMM.msi

И, собственно, на этом всё.

Использовавшиеся источники:
http://7zsfx.info/ru/
http://paraglidernc.com/utilities/sfxsetup.htm

P.S. Важное дополнение. Оказывается, при публикации инсталляционных пакетов есть две возможности: назначить Пользовательский интерфейс при установке Простой или Полный. Простой интерфейс не позволяет создавать диалоговые окна, соответственно, если утилита UUU.exe хочет пообщаться с пользователем, процесс инсталляции вылетает с ошибкой "Не удалось назначить приложение *** из политики ***. Ошибка: в процессе установки произошла неисправимая ошибка".

Вышеуказанный конвертер генерирует пакеты, у которых этот самый Пользовательский интерфейс может быть только Простой. (Возможно, причина вот в этом: The Maximum UI option shows the UI that the author of the Windows Installer package defined.) Если требуется Полный интерфейс, то можно воспользоваться другим конвертером: http://www.exemsi.com/download.

четверг, 13 февраля 2014 г.

Почему я с недоверием отношусь к сложным конструкциям: С++

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

Вот, например. Пишем файл main.cpp примерно такого вида:
#include <iostream>
using namespace std;

int main()
{
    int a[2];
    a[0] = 1; a[1] = 2;
    int t = 1;

    a[t] = a[--t + 1] + 1;

    cout << t << " = " << a[0] << "  " << a[1] << "\n";
}
Компилируем командой gcc main.cpp -lstdc++, запускаем. На экране выводится:
0 = 3 2
Практически тот же самый код:
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    std::vector<int> a(2);
    a[0] = 1; a[1] = 2;
    int t = 1;

    a[t] = a[--t + 1] + 1;

    cout << t << " = " << a[0] << "  " << a[1] << "\n";
}
Выводит на экран:
0 = 1 3

Разница только в объявлениях. Вот как с этим можно работать?! Как по минному полю ходить...