воскресенье, 22 мая 2011 г.

Перевод из DOS-866 на Windows-1251 в MS Access

Столкнулся на работе с такой проблемой. Нужно было средствами VBA загрузить текстовый файл в базу данных MS Access. Сделать это нужно было средствами VBA, т.к. текстовый файл не во всех местах имел четкую структуру и записи в таблицах были разделены на 2 строчки. Кроме того, файлов было более 500, т.е. стандартный импорт данных мне никак не подходил.
Все бы ничего, если бы не одна сложность. Файлы были в кодировке DOS-866, а нужна была Win-1251!


Я провел более 15 минут в поисках как преобразовать кодировку строки или читаемого файла в документации MS Access и не нашел! Честно говоря я удивлен, т.к. утилита импорта данных MS Access предлагает такую возможность. В общем Мелкософт как всегда в своем репертуаре. Более того, поиск человеческого способа в интернет тоже ничего не дал. Лишь в одном форуме мне удалось найти кое-что "подходящее". Если конечно вызов WinAPI функций из VBA можно назвать нормальной практикой программирования в MS Access.

Исходный код для преобразования DOS-866 в Windows-1251 на VBA:

Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As String, ByVal cchWideChar As Long, ByVal lpMultiByteStr As String, ByVal cchMultiByte As Long, ByVal lpDefaultChar As String, ByVal lpUsedDefaultChar As Long) As Long
Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As String, ByVal cchMultiByte As Long, ByVal lpWideCharStr As String, ByVal cchWideChar As Long) As Long
Private Enum eeCharSet
DOS = 866
windows = 1251
End Enum

Private Function ConvertStr(ByVal strSrc As String, _
ByVal nFromCP As eeCharSet, _
ByVal nToCP As eeCharSet) As String
Dim nLen As Long
Dim strDst As String
Dim strRet As String
Dim nRet As Long

nLen = Len(strSrc)
strDst = String(nLen * 2, Chr(0))
strRet = String(nLen * 2, Chr(0))
nRet = MultiByteToWideChar(nFromCP, &H1, strSrc, nLen, strDst, nLen)
nRet = WideCharToMultiByte(nToCP, 0, strDst, nRet, strRet, nLen * 2, ByVal 0, 0)
ConvertStr = Left(strRet, nRet)
End Function