Форум программистов, компьютерный форум, киберфорум
Наши страницы
VBA
Войти
Регистрация
Восстановить пароль
 
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
#1

Чтение файлов формата .txt в кодировке utf-8 - VBA

09.03.2017, 14:34. Просмотров 1866. Ответов 15

Уважаемые форумчане!

Делаю скрипт для чтения и записи txt-файлов из Excel-вского файла по средствам VBA макросов.
Но всё упёрлось в проблему с кодировкой. Мне по умолчанию нужна UTF-8, так как она удобнее и файлы с которыми будет работать скрипт будут именно в ней.
Взял за основу для чтения и записи такой скрипт:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Sub Test()
    ' Запись в файл
    Open "D:\tmp\file.txt" For Output As #1
    Print #1, "My name is Петя!"
    Close #1
  
    ' Чтение из файла
    Open "D:\tmp\file.txt" For Input As #1
    Dim s As String
    Input #1, s
    MsgBox s
    Close #1
End Sub
Проблема в том, что записывать (если понадобится) или считыватт прийдётся txt-шники с «charset = Utf-8», а Excel по-умолчанию работает с ANSI.

Из решений просмотрел в net-е. И думал нашёл функцию StrConv(s, vbUnicode) и StrConv(s, vbFromUnicode)
Но увы... получается, что она не выполняет конвертацию в кодировку юникод и обратно.

Существуют ли какие-нибудь функции для решения этой проблемы?

http://www.cyberforum.ru/vba/thread538716.html

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.03.2017, 14:34
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Чтение файлов формата .txt в кодировке utf-8 (VBA):

Консолидация таблиц одинакового формата из разных файлов
Добрый день! Возникла задача разработать инструмент, объединяющий таблицы из...

Чтение конкретных строк из txt (2 - 5)
Подкиньте, пожалуйста, пример (на VB) чтения, например, со 2 строки txt файла...

Чтение и запись данных из txt в Excel
Всем привет! Подскажите, пожалуйста, как записать в Excel данные из...

Чтение txt-файла с определенного места
Здравствуйте товарищи ! Подскажи как реализовать копирование данных из .txt с...

Чтение из файла .txt построчно в разные textbox
Добрый день! У меня такая проблема: посмотрев множество сайтов я не нашел...

15
smeckoi77
57 / 57 / 15
Регистрация: 13.02.2017
Сообщений: 173
09.03.2017, 15:48 #2
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function ChangeFileCharset(ByVal filename$, ByVal DestCharset$, _
                           Optional ByVal SourceCharset$) As Boolean
    ' функция перекодировки (смены кодировки) текстового файла
   ' В качестве параметров функция получает путь filename$ к текстовому файлу,
   ' и название кодировки DestCharset$ (в которую будет переведён файл)
   ' Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .LoadFromFile filename$    ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
        .Charset = DestCharset$    ' назначаем новую кодировку
       .Open
        .WriteText FileContent$
        .SaveToFile filename$, 2   ' сохраняем файл уже в новой кодировке
       .Close
    End With
    ChangeFileCharset = Err = 0
End Function
Добавлено через 2 минуты
Visual Basic
1
ChangeFileCharset "C:/file.txt",  "Windows-1251", "UTF-8"
1
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
09.03.2017, 21:37  [ТС] #3
спасибо за помощь, к сожалению при испытании этого кода, ничего не получилось:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Function ChangeFileCharset(ByVal filename$, ByVal DestCharset$, Optional ByVal SourceCharset$) As Boolean
   ' функция перекодировки (смены кодировки) текстового файла
   ' В качестве параметров функция получает путь filename$ к текстовому файлу,
   ' и название кодировки DestCharset$ (в которую будет переведён файл)
   ' Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .LoadFromFile filename$   ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
        .Charset = DestCharset$   ' назначаем новую кодировку
       .Open
        .WriteText FileContent$
        .SaveToFile filename$, 2  ' сохраняем файл уже в новой кодировке
       .Close
    End With
    ChangeFileCharset = Err = 0
End Function
 
    
Sub TEST()
ChangeFileCharset "E:\TMP\1.txt", "Windows-1251", "UTF-8"
 
End Sub
Файл пересохраняется, но обработка происходит некорретно. В исходный файл 1.txt записывал строку "My name is Петя". Сам файл сохранил в 1251 (и в UTF 8) - возвращает что то вроде «My name is ????» или «My name is Ïåòÿ» и т.п (в зависимости от вариации. Но никакая не позволила определить, что к чему.

Я вот ещё думаю... Сам редактор VBA не может настраиваться, как скажем другие текстовые редакторы скажем в Notepad++ можно же кодировку менять.. Хотя конечно врятли... Просто заметил, что даже когда просто копируешь из VBA-редактора текст в буфер и вставляешь в блокнот, то сразу вылезают кракозяблы.?!
0
smeckoi77
57 / 57 / 15
Регистрация: 13.02.2017
Сообщений: 173
09.03.2017, 21:52 #4
Попробуйте поменять местами

Visual Basic
1
ChangeFileCharset "C:/file.txt",  "UTF-8", "Windows-1251"
0
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
09.03.2017, 22:23  [ТС] #5
пробовал местами менять, и тоже в разных вариантах исходный текст писал (UTF8 и 1251), но при каждом включении макроса бьются русские символы, а иногда и английские... попробую наверное ещё с iconv() функцией скомбинировать код, она тоже как то на кодировке влияет, правда коряво и не так.. токо синтаксис с объектами для меня сложноват..
0
SoftIce
comment ca va
10413 / 3915 / 999
Регистрация: 27.07.2011
Сообщений: 9,475
Завершенные тесты: 1
10.03.2017, 07:14 #6
Eskander88, если файл в кодировке UTF-8, то функция ChangeFileCharset работает хорошо, я проверил.
Менять параметры местами не нужно.
Естественно, что применять эту функцию к файлу нужно только один раз.
0
_shark
139 / 146 / 23
Регистрация: 11.10.2016
Сообщений: 480
10.03.2017, 09:19 #7
Цитата Сообщение от Eskander88 Посмотреть сообщение
Просто заметил, что даже когда просто копируешь из VBA-редактора текст в буфер и вставляешь в блокнот, то сразу вылезают кракозяблы
чтобы не было кракозябров, нужно перед копированием всего лишь перейти на русскую раскладку клавиатуры
0
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
10.03.2017, 17:20  [ТС] #8
.. ещё раз протестил. Разобрался в чём дело. Проверил логику приложения, оказывается допустил банальную ошибку.
Visual Basic
1
ChangeFileCharset "D:\TMP\1.txt", "UTF-8", "UTF-8"
иначе конечно код считывает "UTF-8" а записывает в "Windows-1251", и опять такую же процедуры не проделаешь, а программа Блокнот так быстро не реагирует на смену кодировки.

Единственное какой для меня недостаток, то что для меня данная синтаксическая конструкция малость гоняет в ступор.
Так как считывание и запись происходит в теле функции, при этом работа происходит с объектом. Это конечно хоть, что-то, чтение и запись происходит, но от этого легче не становится.
Нужно же получить данные в переменную а потом обработать с помощью имеющихся процедур, прийдётся огород городить или в справочник погрузится.
0
SoftIce
comment ca va
10413 / 3915 / 999
Регистрация: 27.07.2011
Сообщений: 9,475
Завершенные тесты: 1
10.03.2017, 17:27 #9
Тогда можно предложить менять кодировку "на лету", а кодировку файла не трогать, пуст так и будет UTF-8.
0
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
10.03.2017, 17:34  [ТС] #10
я в общем то и полагал так делать, вроде
Visual Basic
1
2
3
4
5
6
7
8
    ' Чтение из файла
    Open "D:\tmp\file.txt" For Input As #1
    Dim s As String
    Input #1, s
    ' Функция д/правильного перекодировки «s»   
    ' Произвольный код д/обработки «s»
    MsgBox s
    Close #1
.. и потом таким же макаром запись в *.txt файл, с перекодированием - если понадобится.
Но готовой функции как таковой нет, пока имеем такой предложенный вариант
0
SoftIce
comment ca va
10413 / 3915 / 999
Регистрация: 27.07.2011
Сообщений: 9,475
Завершенные тесты: 1
10.03.2017, 17:41 #11
Цитата Сообщение от Eskander88 Посмотреть сообщение
Но готовой функции как таковой нет
На вскидку могу предложить что-то подобное.
Но с первым байтом нужно что-то делать.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Sub Test()
    ' Запись в файл
    ' Open "C:\tmp\file.txt" For Output As #1
    ' Print #1, "My name is Петя!"
    ' Close #1
  
    ' Чтение из файла
    Open "C:\tmp\file.txt" For Input As #1
      Dim s As String
      Input #1, s
    Close #1
    MsgBox UTF8ToANSI(s)
End Sub
 
Public Function UTF8ToANSI(ByVal UTF8 As String) As String
    Dim UTF8Chars() As String, i As Long
    UTF8Chars = UTF8Chr
    For i = 128 To 255
         UTF8 = Replace(UTF8, UTF8Chars(i - 128), Chr(i))
    Next i
    UTF8ToANSI = UTF8
End Function
Public Function UTF8Chr()
    UTF8Chr = Split("Р‚&&Рѓ&&‚&&С“&&„&&…&&вЂ*&&‡&&€&&‰&&Р‰&&‹&&РЉ&&РЊ&&Р‹&&РЏ&&С’&&вЂЛњ&&’&&“&&”&&•&&–&&—&&ВЛњ&&в„ў&&С™&&›&&Сљ&&Сњ&&С›&&Сџ&&В*&&РЋ&&Сћ&&Р€&&В¤&&Тђ&&В¦&&В§&&РЃ&&В©&&Р„&&В«&&В¬&&В*&&В®&&Р‡&&В°&&В±&&Р†&&С–&&Т‘&&Вµ&&В¶&&В·&&С‘&&в„–&&С”&&В»&&СЛњ&&Р…&&С•&&С—&&Рђ&&Р‘&&Р’&&Р“&&Р”&&Р•&&Р–&&Р—&&РЛњ&&Р™&&Рљ&&Р›&&Рњ&&Рќ&&Рћ&&Рџ&&Р*&&РЎ&&Рў&&РЈ&&Р¤&&РҐ&&Р¦&&Р§&&РЁ&&Р©&&РЄ&&Р«&&Р¬&&Р*&&Р®&&РЇ&&Р°&&Р±&&РІ&&Рі&&Рґ&&Рµ&&Р¶&&Р·&&Рё&&Р№&&Рє&&Р»&&Рј&&РЅ&&Рѕ&&Рї&&СЂ&&СЃ&&С‚&&Сѓ&&С„&&С…&&С†&&С‡&&С€&&С‰&&СЉ&&С‹&&СЊ&&СЌ&&СЋ&&СЏ", "&&")
End Function
0
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
10.03.2017, 17:48  [ТС] #12
.. а если использовать вариант, что предложил smeckoi77? Только добавить возможность возврата свойства объекта - имею ввиду переменную с записанными в неё данными из файла. У меня к сожалению навыков по VBA маловато, не могу вернуть значение из функции от объекта, как я понял там должен быть специальный метод д/реализации. Использовать функции getFile и putFile на базе ChangeFileCharset
0
smeckoi77
57 / 57 / 15
Регистрация: 13.02.2017
Сообщений: 173
10.03.2017, 17:52 #13
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Function ChangeTextCharset(ByVal txt$, ByVal DestCharset$, _
                           Optional ByVal SourceCharset$) As String
    ' функция перекодировки (смены кодировки) текстовой строки
   ' В качестве параметров функция получает текстовую строку txt$,
   ' и название кодировки DestCharset$ (в которую будет переведён текст)
   ' Функция возвращает текст в новой кодировке
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2: .Mode = 3
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .WriteText txt$
        .Position = 0
        .Charset = DestCharset$    ' назначаем новую кодировку
       ChangeTextCharset = .ReadText
        .Close
    End With
End Function
0
Homarty
136 / 114 / 27
Регистрация: 12.02.2017
Сообщений: 308
11.03.2017, 14:16 #14
Кривой вариант немного
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Sub Test()
    Dim s As String
    Dim x() As Byte, xx() As Byte
    Dim i As Long, y As Long
    Dim ii As Long
    Open "d:\tmp\file.txt" For Binary As #1
        s = "My name is Петя!"
        x = StrConv(s, vbUnicode)
        y = UBound(x)
        ReDim xx(0 To y \ 2)
        ii = 0
        For i = 0 To y Step 2
            xx(ii) = x(i)
            ii = ii + 1
        Next i
        Put #1, , xx
    Close #1
    y = FileLen("d:\tmp\file.txt")
    Open "d:\tmp\file.txt" For Binary As #1
        ReDim xx(0 To y - 1)
        ReDim x(0 To 2 * (y - 1))
        Get #1, , xx
        ii = 0
        For i = 0 To 2 * (y - 1) Step 2
            x(i) = xx(ii)
            ii = ii + 1
        Next i
        s = StrConv(x, vbFromUnicode)
        MsgBox s
    Close #1
End Sub
Добавлено через 16 часов 16 минут
Этот вариант более эстетичный
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Sub Test()
    Dim  xx() As Byte
    xx = "My name is Петя!"
    Open "d:\tmp\file.txt" For Binary As #1
        Put #1, , xx
    Close #1
    Open "d:\tmp\file.txt" For Binary As #1
        Get #1, , xx
    Close #1
    MsgBox xx
End Sub
0
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
12.03.2017, 15:57  [ТС] #15
воспользовавшись примером, получилось нечто такое..

Функция для обмена данными с файлом

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function exChangeContent(ByVal str$, ByVal filename$, ByVal DestCharset$, Optional ByVal SourceCharset$) As String
   ' функция перекодировки (смены кодировки) текстового файла
   ' В качестве параметров функция получает путь filename$ к текстовому файлу,
   ' и название кодировки DestCharset$ (в которую будет переведён файл)
   ' Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .LoadFromFile filename$   ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
        .Charset = DestCharset$   ' назначаем новую кодировку
       .Open
        .WriteText str$
        .SaveToFile filename$, 2  ' сохраняем файл уже в новой кодировке
       .Close
    End With
'   exChangeContent = FileContent$     ' обменяет знач.ячейки с содержимым файла
    exChangeContent = ActiveCell.Value  ' вернёт текущее значение ячейки
End Function
и такая процедура, для запуска

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Sub TEST()
 
Dim str As String  'Текст для записи в файл.
Dim pth As String  'Путь к файлу + имя.расширение
Dim chI As String  'Кодировка входящего текста
Dim chO As String  'Кодировка исходящего текста
 
' Значения по умолчанию
str = "Текстовый файлик"
pth = "E:\TMP\1.txt"
chI = "UTF-8"
chO = "UTF-8"
 
 
' Берём путь к файлу из соседней ячейки справа от выделенной
  If Len(ActiveCell.Offset(0, 1).Value) Then pth = ActiveCell.Offset(0, 1).Value
  
  
  str = ActiveCell.Text
  ActiveCell.Value = exChangeContent(str, pth, chI, chO)
 
End Sub

скрипт рабочий. В принципе необходимые задачи решает. Только получается что «On Error Resume Next: Err.Clear» вроде как в холостую, хотя по идеи надо как то обработать ошибку..
0
Eskander88
0 / 0 / 2
Регистрация: 02.11.2015
Сообщений: 83
20.04.2017, 18:40  [ТС] #16
Переписал макрос. Сделал пример только для считывания.
Выглядит следующим образом:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Function exChangeContent(ByVal str$, ByVal pth$, ByVal chI$, Optional ByVal chO$) As String
   ' функция перекодировки (смены кодировки) текстового файла
   ' pth$ - путь к текстовому файлу с названием файла.расширение,
   ' chI$ кодировка в которой перевести для принятия файла
   ' ? Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
 
 
        .Type = 2
        If Len(chO$) Then .Charset = chO$    ' указываем исходную кодировку
       .Open
        .LoadFromFile pth$   ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
       
'   Блок кода, чтобы записать значение в файл
'       .Charset = chI$   ' назначаем новую кодировку
'        .Open
'      .WriteText str$
'       .SaveToFile pth$, 2  ' сохраняем файл уже в новой кодировке
'      .Close
 
    End With
    
 
    exChangeContent = FileContent$    
 
End Function
 
Sub TEST()
 
Dim str As String  'Текст для записи в файл.
Dim pth As String  'Путь к файлу + имя.расширение
Dim chI As String  'Кодировка входящего текста
Dim chO As String
 
' Значения по умолчанию
str = "Текстовый файлик"    ' Значение по-умолчанию
pth = "D:\tmp\русский.txt"    ' Значение по-умолчанию
chI = "UTF-8"
chO = "UTF-8"
 
 
 
' Берём путь к файлу из ячейки, если есть
 If Len(ActiveCell.Offset(0, 1).Value) Then pth = ActiveCell.Offset(0, 1).Value
 
 
  
  str = ActiveCell.Text
  ActiveCell.Value = exChangeContent(str, pth, chI, chO)
 
 
End Sub
макрос не работает, если в ячейке справа, есть путь с кириллическими символами.
Этот EXCEL оказывается ещё тот русофоб ))), причём файлы с директорией типа «D:\tmp\§patagraph.txt» он считывает!

Подскажите пожалуйста..
Как сделать, чтобы макрос понимал в адресе к файлу не только UTF-8 в тексте файла, но и русскоязычные символы?
Или в чём хотя бы может быть дело?
варианты пробовал вместо «D:\tmp\русский.txt» поставить так «D:\tmp\ðóññêèé.txt» — ноль реакции

Добавлено через 7 минут
Тут ещё такой полтергейст для путей с кириллицей! Если файл существует, то скрипт вернёт его путь, - а если нет, - то сделает ячейку пустой?
0
20.04.2017, 18:40
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.04.2017, 18:40
Привет! Вот еще темы с решениями:

Excel чтение txt таблицы с tab разделителями
помогите считать фаил txt таблицы с текстами разделенными \t , полазил по...

Чтение данных из txt файла и запись их в Excel
помогите пожалста. Такая вот проблемка. Есть файл (*.txt) в нём такой вот...

Чтение текста в Юникоде из txt файла в столбец Excel 2010
В общем пытаюсь прочесть, но корректно (без кракозябр) получается только первая...

Помогите с макросом для обработки файлов txt
Здравствуйте! Проблема такая: в папке на диске С лежат текстовые файлы,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru