Имя: Пароль:
1C
1C 7.7
v7: Падает скрипт перекодировки UTF8->1251
,
0 Злопчинский
 
02.11.24
19:38
Имеем такую штуку
глИзменитьКодовуюСтраницуФайла(ВыбФайл, "UTF-8", "Windows-1251");

Процедура глИзменитьКодовуюСтраницуФайла(имяФайла, исходнКодировка, нужнаяКодировка) Экспорт
	Если ФС.СуществуетФайл(имяФайла) = 0 Тогда
		Сообщить("Файл " + имяФайла + " - не найден! Изменение кодировки отменено.", "!");
		Возврат;
	КонецЕсли;
	ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
	ScrptCtrl.Language = "VBScript";
	ScrptCtrl.AddCode("
		|Function StrConv(Text,SourceCharset,DestCharset)
		|	Set Stream=CreateObject(""ADODB.Stream"")
		|	Stream.Type=2
		|	Stream.Mode=3
		|	Stream.Open
		|	Stream.Charset=DestCharset
		|	Stream.WriteText Text
		|	Stream.Position=0
		|	Stream.Charset=SourceCharset
		|	StrConv=Stream.ReadText
		|End Function
		|
		|sub ConvertCodepage( fileName, SourceCharset, DestCharset )
		|	set fs = CreateObject(""Scripting.FilesystemObject"")
		|	originalText = fs.openTextFile(fileName,1).readAll()
		|	convertedText = strConv(originalText, SourceCharset, DestCharset )
		|	fs.openTextFile(fileName,2,true).write(convertedText)
		|end sub
		|
		|");
	Module = ScrptCtrl.Modules("Global");
	CodeObject = Module.CodeObject;
	CodeObject.ConvertCodepage(имяФайла, исходнКодировка, нужнаяКодировка);
КонецПроцедуры //ИзменитьКодовуюСтраницуФайла()


Суть проблемы - один файл нормально обрабатывает, на другом - падает с ошибкой
CodeObject.ConvertCodepage(имяФайла, исходнКодировка, нужнаяКодировка);
{Глобальный модуль(1869)}: Ошибка выполнения Microsoft VBScript: Недопустимый вызов или аргумент процедуры


в чем разница - не понимаю...
куда смотреть, что отлавливать?
1 dedmoroz777
 
02.11.24
18:20
Путь к файлам одинаковый?
2 Злопчинский
 
02.11.24
18:29
путь одинаковый. укорочен до беспроблемности.
sellerbad - проблемный
3 Злопчинский
 
02.11.24
18:59
могу, конечно, и файлы выложить, если это поможет...
4 Franchiser
 
гуру
02.11.24
19:06
(0) а если чисто на vbs написать то какая ошибка?
5 Franchiser
 
гуру
02.11.24
19:39
Function StrConv(Text,SourceCharset,DestCharset)
	Set Stream=CreateObject("ADODB.Stream")
	Stream.Type=2
	Stream.Mode=3
	Stream.Open
	Stream.Charset=DestCharset
	On Error Resume Next
	Stream.WriteText Text
	If Err.Number <> 0 Then
		MsgBox "Ошибка при записи текста в поток: " & Err.Description
		On Error GoTo 0
		Exit Function
	End If
	Stream.Position=0
	Stream.Charset=SourceCharset
	StrConv=Stream.ReadText
	On Error GoTo 0
End Function
6 Злопчинский
 
02.11.24
19:40
Сейчас проверю
7 MWWRuza
 
гуру
02.11.24
19:43
Если надо строку конвертить, то можно карлика заюзать...

# Встроенные конвертеры
СтрокаUTF8   = Карлик.ToUTF8(СтрокаASCII)
СтрокаASCII  = Карлик.FromUTF8(СтрокаUTF8)
СтрокаURL    = Карлик.ToURL(СтрокаASCII)
СтрокаASCII  = Карлик.FromURL(СтрокаURL)
СтрокаBASE64 = Карлик.ToBASE64(СтрокаASCII)
СтрокаASCII  = Карлик.FromBASE64(СтрокаBASE64)

С файлами сложнее - тут, хочешь не хочешь через поток придется делать... Все от задачи зависит.
8 Злопчинский
 
02.11.24
19:48
(5) не получаеся
то же самое выдает
CodeObject.ConvertCodepage(имяФайла, исходнКодировка, нужнаяКодировка);
{Глобальный модуль(1876)}: Ошибка выполнения Microsoft VBScript: Недопустимый вызов или аргумент процедуры
    19:46:52: формат обработки CSV, обработка не выполнена..?!
9 Злопчинский
 
02.11.24
19:49
Текущий код
10 Злопчинский
 
02.11.24
19:53
таакс.. чтото наклюнулось... пару мин
11 Злопчинский
 
02.11.24
20:01
Не, все без изменений...
12 Злопчинский
 
02.11.24
20:07
тупо падает ммежду КТ100 и КТ200

        |sub ConvertCodepage( fileName, SourceCharset, DestCharset )
        |    set fs = CreateObject(""Scripting.FilesystemObject"")
        |    originalText = fs.openTextFile(fileName,1).readAll()
        |    convertedText = strConv(originalText, SourceCharset, DestCharset )
        |     MsgBox ""кт100""
        |    fs.openTextFile(fileName,2,true).write(convertedText)
        |     MsgBox ""кт200""
13 Злопчинский
 
02.11.24
20:09
Если вот так
Процедура глИзменитьКодовуюСтраницуФайла(имяФайла, исходнКодировка, нужнаяКодировка) Экспорт
    Если ФС.СуществуетФайл(имяФайла) = 0 Тогда
        Сообщить("Файл <" + имяФайла + "> - не найден! Изменение кодировки отменено.", "!");
        Возврат;
    КонецЕсли;
    ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
    ScrptCtrl.Language = "VBScript";
    ScrptCtrl.AddCode("
        |Function StrConv(Text,SourceCharset,DestCharset)
        |    MsgBox ""кт1""
        |    Set Stream=CreateObject(""ADODB.Stream"")
        |    Stream.Type=2
        |    Stream.Mode=3
        |    Stream.Open
        |    Stream.Charset=DestCharset
        |    MsgBox ""кт2""
        |    On Error Resume Next
        |    MsgBox ""кт3""
        |    Stream.WriteText Text
        |    MsgBox ""кт4""
        |    If Err.Number <> 0 Then
        |        MsgBox ""Ошибка при записи текста в поток: "" & Err.Description
        |        On Error GoTo 0
        |        Exit Function
        |    End If
        |    MsgBox ""кт5""
        |    Stream.Position=0
        |    MsgBox ""кт6""
        |    Stream.Charset=SourceCharset
        |    MsgBox ""кт7""
        |    StrConv=Stream.ReadText
        |    MsgBox ""кт8""
        |    On Error GoTo 0
        |    MsgBox ""кт9""
        |End Function
        |
        |sub ConvertCodepage( fileName, SourceCharset, DestCharset )
        |    set fs = CreateObject(""Scripting.FilesystemObject"")
        |    originalText = fs.openTextFile(fileName,1).readAll()
        |    convertedText = strConv(originalText, SourceCharset, DestCharset )
        |     MsgBox ""кт100""
        |    fs.openTextFile(fileName,2,true).write(convertedText)
        |     MsgBox ""кт200""
        |end sub
        |
        |");
    Module = ScrptCtrl.Modules("Global");
    CodeObject = Module.CodeObject;
        Сообщить("имяФайла=<"+имяФайла+">");
        Сообщить("исходнКодировка=<"+исходнКодировка+">");
        Сообщить("нужнаяКодировка=<"+нужнаяКодировка+">");
    CodeObject.ConvertCodepage(имяФайла, исходнКодировка, нужнаяКодировка);
КонецПроцедуры //ИзменитьКодовуюСтраницуФайла()

то выдает все от КТ1 до КТ9, потом КТ100 и облом...
14 Franchiser
 
гуру
02.11.24
20:12
(13) а если убрать функцию strconv и написать сплошным текстом?
15 Злопчинский
 
02.11.24
20:14
это как?
16 Franchiser
 
гуру
02.11.24
20:18
Хотя у тебя между кт100 и кт200 же падает. Тогда туда добавь обработку ошибки - перед opentextfile
17 Злопчинский
 
02.11.24
20:22
написал так:
18 Злопчинский
 
02.11.24
20:22
Процедура глИзменитьКодовуюСтраницуФайла1(имяФайла, исходнКодировка, нужнаяКодировка) Экспорт
    Если ФС.СуществуетФайл(имяФайла) = 0 Тогда
        Сообщить("Файл <" + имяФайла + "> - не найден! Изменение кодировки отменено.", "!");
        Возврат;
    КонецЕсли;
    ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
    ScrptCtrl.Language = "VBScript";
    ScrptCtrl.AddCode("
        |sub ConvertCodepage( fileName, SourceCharset, DestCharset )
        |   set fs = CreateObject(""Scripting.FilesystemObject"")
        |   originalText = fs.openTextFile(fileName,1).readAll()
        |    MsgBox ""кт1""
        |    Set Stream=CreateObject(""ADODB.Stream"")
        |    Stream.Type=2
        |    Stream.Mode=3
        |    Stream.Open
        |    Stream.Charset=DestCharset
        |    MsgBox ""кт2""
        |    On Error Resume Next
        |    MsgBox ""кт3""
        |    Stream.WriteText convertedText
        |    MsgBox ""кт4""
        |    If Err.Number <> 0 Then
        |        MsgBox ""Ошибка при записи текста в поток: "" & Err.Description
        |        On Error GoTo 0
        |        Exit Function
        |    End If
        |    MsgBox ""кт5""
        |    Stream.Position=0
        |    MsgBox ""кт6""
        |    Stream.Charset=SourceCharset
        |    MsgBox ""кт7""
        |    StrConv=Stream.ReadText
        |    MsgBox ""кт8""
        |    On Error GoTo 0
        |    MsgBox ""кт9""
        |     MsgBox ""кт100""
        |    fs.openTextFile(fileName,2,true).write(convertedText)
        |     MsgBox ""кт200""
        |end sub
        |
        |");
    Module = ScrptCtrl.Modules("Global");
    CodeObject = Module.CodeObject;
        Сообщить("имяФайла=<"+имяФайла+">");
        Сообщить("исходнКодировка=<"+исходнКодировка+">");
        Сообщить("нужнаяКодировка=<"+нужнаяКодировка+">");
    CodeObject.ConvertCodepage(имяФайла, исходнКодировка, нужнаяКодировка);
КонецПроцедуры //ИзменитьКодовуюСтраницуФайла1()
19 Злопчинский
 
02.11.24
20:23
пофиг, нормальный файл все проходит норм,
проблемный - падает после КТ100
20 Злопчинский
 
02.11.24
20:30
(16) хз как. я на VB не писал никогда...
21 Franchiser
 
гуру
02.11.24
20:28
Попробуй 4й параметр указать в opentextfile
22 Franchiser
 
гуру
02.11.24
20:29
И может быть имеет смысл разделить opentextfile и write в последней строке
23 osa1C
 
02.11.24
20:29
Может всё же проблема в разной исходной кодировке?
24 Злопчинский
 
02.11.24
20:35
(23) см (0) - первые байты файлов - одинаковые..
?
25 Злопчинский
 
02.11.24
20:38
(22) хз, говорю же - не писал.
попытка без функции не удалась, развалилось, требует SUB
26 Franchiser
 
гуру
02.11.24
20:39
EF BB BF это utf8
27 Злопчинский
 
02.11.24
20:44
ну это и по постановке задачи видно со скринов в (0)
28 Franchiser
 
гуру
02.11.24
20:46
Если убрать строку
fs.openTextFile(fileName,2,true).write(convertedText) ошибка пропадает?
29 Злопчинский
 
02.11.24
20:51
(28) вернул все в (0)
убрал строку.
ошибка пропадает, отрабатывает норм.
30 Franchiser
 
гуру
02.11.24
20:56
Перепиши последнюю строку как то так
set fs = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
set file = fs.OpenTextFile(fileName, 2, True)
file.WriteText convertedText
file.Close
If Err.Number <> 0 Then
              MsgBox ""Ошибка при записи: "" & Err.Description
                On Error GoTo 0
31 Franchiser
 
гуру
02.11.24
20:58
Все таки не понятно ошибка возникает на opentextfile() или на write()
32 Злопчинский
 
02.11.24
21:00
сейчас
33 Злопчинский
 
02.11.24
21:01
редуцировал файл половинным делением, прошло на минимумуе, разбираюсь...
34 Franchiser
 
гуру
02.11.24
21:01
Кстати а ты пишешь в новый файл или в старый который конвертируется ?
35 Злопчинский
 
02.11.24
21:09
(30)         |sub ConvertCodepage( fileName, SourceCharset, DestCharset )
        |    set fs = CreateObject(""Scripting.FilesystemObject"")
        |    originalText = fs.openTextFile(fileName,1).readAll()
        |    convertedText = strConv(originalText, SourceCharset, DestCharset )
        |   set fs = CreateObject(""Scripting.FileSystemObject"")
        |   On Error Resume Next
        |   set file = fs.OpenTextFile(fileName, 2, True)
        |   file.WriteText convertedText
        |   file.Close
        |   If Err.Number <> 0 Then
        |      MsgBox ""Ошибка при записи: "" & Err.Description
        |      On Error GoTo 0
        |   End If
        |end sub

ругалось на If, добавил end If перед end sub - ????
ругается
36 osa1C
 
02.11.24
21:09
Попробуй так:

Set f = fs.openTextFile(fileName,2,true)
f.write(convertedText)
f.Close
37 Franchiser
 
гуру
02.11.24
21:10
Тогда вместо writetext напиши write
38 Злопчинский
 
02.11.24
21:19
предварительно:
вот это ему не нравится
39 Злопчинский
 
02.11.24
21:20
убрал знаки рубля и все прошло норм...
40 Franchiser
 
гуру
02.11.24
21:20
Ну возможно: в некоторых кодировках может не быть такого символа. Тогда наверно нужно сделать замену символа перед перекодировкой
41 Злопчинский
 
02.11.24
21:22
(36) (37) все равно ломается на проблемном файле ;-)
42 Злопчинский
 
02.11.24
21:24
(40) это понятно, но тогда при перекодировке такого символа что получится?
43 Franchiser
 
гуру
02.11.24
21:30
Ничего, наверно ошибка будет
44 Злопчинский
 
02.11.24
21:32
Formex Стр = глСервис.EncodeFromUTF8(Стр); при перекодировке просто вбабахивает на такой символ как "?"
45 Злопчинский
 
02.11.24
21:33
(43) вот она и была. только мутная и непонятная.
46 Злопчинский
 
02.11.24
21:33
(7) UTF можно и формексом конвертить
47 Franchiser
 
гуру
02.11.24
21:48
Символ ₽ (рубль) не входит в стандартный набор символов Windows-1251, из-за чего и возникает ошибка при конвертации. - ответ gpt
48 Franchiser
 
гуру
02.11.24
21:50
Символ ₽ (рубль) был добавлен в стандарт Unicode в версии 7.0, выпущенной в 2014 году. Кодировка Windows-1251, также известная как CP1251, была разработана гораздо раньше и не обновлялась для включения новых символов, таких как рубль.

Windows-1251 была создана для поддержки кириллических алфавитов в советских и постсоветских странах и включает только набор символов, которые были актуальны на момент её создания. Новый символ ₽ просто не попал в этот набор.

Для поддержки современных символов лучше использовать Unicode (например, UTF-8), который включает широкий спектр символов и постоянно обновляется. Это обеспечит совместимость с новыми символами и позволит избежать проблем с кодировкой.
49 Злопчинский
 
02.11.24
22:19
(47) это понятно. значит такой код конвертации как в (0) будет падать на любом наборе UTF8, который не отображается в кодировку-приемник.
50 Злопчинский
 
02.11.24
22:20
(47) лучше гпт спросить как сконвертировать, чтобы не падало...
51 Franchiser
 
гуру
03.11.24
01:43
(51) он предлагает заменить символ на сочетание rub
52 Franchiser
 
гуру
03.11.24
01:52
Или такой код предлагает по замене недопустимых символов на вопрос:
sub ConvertCodepage(fileName, SourceCharset, DestCharset)
    On Error Resume Next
    set fs = CreateObject("Scripting.FilesystemObject")
    originalText = fs.openTextFile(fileName, 1, false, SourceCharset).readAll()
    If Err.Number <> 0 Then
        MsgBox "Ошибка чтения файла: " & Err.Description
        On Error GoTo 0
        Exit Sub
    End If

    Set Stream = CreateObject("ADODB.Stream")
    Stream.Type = 2
    Stream.Mode = 3
    Stream.Open
    Stream.Charset = DestCharset

    Dim i, char, resultText
    resultText = ""
    For i = 1 To Len(originalText)
        char = Mid(originalText, i, 1)
        Stream.WriteText char
        Stream.Position = 0
        If Err.Number <> 0 Then
            Stream.Charset = "UTF-8" ' Вернемся к исходной кодировке
            char = "?" ' Замена неподдерживаемого символа
            Stream.WriteText char
            Stream.Position = 0
            Stream.Charset = DestCharset
            Err.Clear
        End If
        resultText = resultText & Stream.ReadText
        Stream.Position = 0
    Next

    On Error GoTo 0
    set outputFile = fs.OpenTextFile(fileName, 2, true, 0)
    outputFile.WriteText resultText
    If Err.Number <> 0 Then
        MsgBox "Ошибка при записи файла: " & Err.Description
        Exit Sub
    End If
    outputFile.Close
    MsgBox "Конвертация завершена успешно"
end sub
53 Franchiser
 
гуру
03.11.24
02:05
Без посимвольной проверки:
Function ReplaceUnsupportedChars(text)
    Dim regex
    Set regex = CreateObject("VBScript.RegExp")
    regex.Global = True
    regex.IgnoreCase = False
    regex.Pattern = "[^\x00-\xFF]" ' Паттерн для символов за пределами стандартного диапазона Windows-1251
    ReplaceUnsupportedChars = regex.Replace(text, "?") ' Можно заменить на любой другой безопасный символ или строку
End Function

Function ReplaceSpecialChars(text)
    Dim regex
    Set regex = CreateObject("VBScript.RegExp")
    regex.Global = True
    regex.IgnoreCase = False
    regex.Pattern = "[^А-Яа-яA-Za-z0-9ёЁ\s.,:;?!()\""-]" ' Паттерн для символов, поддерживаемых Windows-1251
    ReplaceSpecialChars = regex.Replace(text, "?")
End Function

sub ConvertCodepage(fileName, SourceCharset, DestCharset)
    On Error Resume Next
    set fs = CreateObject("Scripting.FilesystemObject")
    originalText = fs.openTextFile(fileName, 1, false, SourceCharset).readAll()
    If Err.Number <> 0 Then
        MsgBox "Ошибка чтения файла: " & Err.Description
        On Error GoTo 0
        Exit Sub
    End If

    ' Заменяем неподдерживаемые символы
    originalText = ReplaceUnsupportedChars(originalText)
    originalText = ReplaceSpecialChars(originalText)
    
    Set Stream = CreateObject("ADODB.Stream")
    Stream.Type = 2
    Stream.Mode = 3
    Stream.Open
    Stream.Charset = DestCharset
    Stream.WriteText originalText
    Stream.Position = 0
    convertedText = Stream.ReadText
    If Err.Number <> 0 Then
        MsgBox "Ошибка при чтении текста из потока: " & Err.Description
        On Error GoTo 0
        Exit Sub
    End If
    On Error GoTo 0
    
    set outputFile = fs.OpenTextFile(fileName, 2, true, 0)
    outputFile.WriteText convertedText
    If Err.Number <> 0 Then
        MsgBox "Ошибка при записи файла: " & Err.Description
        Exit Sub
    End If
    outputFile.Close
    MsgBox "Конвертация завершена успешно"
end sub
54 Злоп
 
03.11.24
05:19
Ух сколько всего... Проверю...
55 MWWRuza
 
гуру
03.11.24
15:47
(46) (7) UTF можно и формексом конвертить

Ага... Просто в карлике белее широкий набор вариантов и туда, и обратно.
56 MWWRuza
 
гуру
03.11.24
15:48
Есть еще куча онлайн-сервисов конвертеров. Что они на твой файл скажут, если им его подсунуть?
57 MWWRuza
 
гуру
03.11.24
15:53
Вот первая попавшаяся ссылка: https://subtitletools.com/convert-text-files-to-utf8-online
На самом деле, их много, с разной степенью "удобности" :-)
58 bmitkin
 
03.11.24
16:09
Сталкивался с похожими проблемами, когда через скрипт пишешь в тот же файл, который читаешь.
Решил через временный файл: один читаешь, в другой пишешь.
59 Злоп
 
03.11.24
17:28
(58) хм, надо проверить такой вариант
60 bmitkin
 
03.11.24
17:58
v7: Перекодировка файла из utf8 в 1251
Похожая тема. Говорят, помогло.
61 Злопчинский
 
04.11.24
14:25
(60) попробовал, работает!
Спасибо.
.
символы, которые нельзя перекодировать, заменяет на "?"
62 Злопчинский
 
04.11.24
14:26
В итоге запилил так
    ADODBStream = CreateObject("ADODB.Stream");
    ADODBStream.Type = 2;

    ADODBStream.Charset = КодировкаОткуда;
    ADODBStream.Open();

    ADODBStream.LoadFromFile(ИмяФайла);
    Text = ADODBStream.ReadText();
    ADODBStream.Close();
    
    ADODBStream.Charset = КодировкаКуда;
    ADODBStream.Open();
    ADODBStream.WriteText(Text);
    ADODBStream.SaveToFile(ИмяФайла,2);
    ADODBStream.Close();
    ADODBStream = "";

    //{--- тоже рабочий вариант, v7: Перекодировка файла из utf8 в 1251#11 ----------------------------------------------------------    
    //Байт=255;
    //СтримВход = СоздатьОбъект("Adodb.Stream");
    //СтримВход.Type = 2;
    //СтримВход.charset = ИзКодировки;
    //СтримВход.Open();
    //СтримВход.LoadFromFile(ВременныйФайл);
    //СтримВыход = СоздатьОбъект("Adodb.Stream");
    //СтримВыход.Type = 2;
    //СтримВыход.charset = ВКодировку;
    //СтримВыход.Open();
    //Пока СтримВход.EOS=0 Цикл
    //    СтримВыход.WriteText(СтримВход.ReadText(Байт),?(Байт=-2,1,0));
    //КонецЦикла;
    //СтримВход.Close();
    //СтримВыход.SaveToFile(ИмяФайла,2);    
    //}--- тоже рабочий вариант, v7: Перекодировка файла из utf8 в 1251#11 ----------------------------------------------------------
63 Franchiser
 
гуру
04.11.24
14:58
(62) в чем принципиальное отличие от того что было изначально? Добавлено loadfromfile?
64 Волшебник
 
04.11.24
15:34
UTF8->1251 ?

хватит разврата...
65 Djelf
 
04.11.24
17:23
(64) В электронных УПД требуется 1251, может разврата еще не хватает?
66 Волшебник
 
04.11.24
17:38
(65) Ну ок. Но это последний раз.
67 MWWRuza
 
гуру
05.11.24
13:23
(66) к (65) В электронных УПД требуется 1251

Как будто это требование от нас или используемой платформы зависит... Это требование оператора ЭДО. Я в свое время тоже с этим "поизвращался"...