Запись текста в кодировке UTF-8 без BOM из 1с 8.2
Разработка - Универсальные функции
Смысл такой: на WEB-сайт потребовалось выгрузить файл в кодировке UTF-8. Но проблема в том, что UTF-8 имеет 2 варианта: "с BOM" и "без BOM". Файлы, сохраненные в этих двух кодировках, получаются одинаковые за исключением того, что в первом случае в начало файла добавлены три байта EF BB BF (в 16-ричной системе счисления). Это и есть символы BOM (сигнатура Byte Order Mark). Так вот, на сайт нужно было отправить "без BOM", а 1с 8.2 сохраняет исключительно "с BOM".
Вот из-за того, что 1с 8.2 не может сохранять текстовые файлы в нужном мне формате и возникла идея "вырезать" эти символы из двоичного файла, но как это сделать в 1с 8.2, я не нашел. Там вообще работа с двоичными данными очень ограничена.
Поэтому пошел по простому пути: что не изобретено, на том катаемся.
Придумал через "очень много" так:
это приблизительный код вызова:
текст = Новый ТекстовыйДокумент;
...
здесь в "текст" что-то пихаем
...
папкаФайла = "какая-то папка\";
папкаВОМ = папкаФайла+"temp_BOM\";
имяФайла = "как-то.почему-то";
СоздатьКаталог(папкаВОМ);
текст.Записать(папкаВОМ+имяФайла, КодировкаТекста.UTF8, Символы.ВК);
УбитьВОМ(папкаВОМ+имяФайла, папкаФайла+имяФайла, папкаВОМ);
далее непосредственно главная процедура "УбитьВОМ":
Процедура УбитьВОМ(Знач ИсходныйФайл, РезультирующийФайл, ВременнаяПапка, МассивФайлов = Неопределено)
Если МассивФайлов = Неопределено Тогда
МассивФайлов = Новый Массив;
КонецЕсли;
бин = Новый ДвоичныеДанные(ИсходныйФайл);
размер = бин.Размер();
новыйРазмер = Макс(Окр(размер/2,0),3);
массив = РазделитьФайл(ИсходныйФайл,новыйРазмер);
Если массив.Количество() = 2 Тогда
МассивФайлов.Вставить(0,массив[1]);
КонецЕсли;
Если новыйРазмер = 3 Тогда
ОбъединитьФайлы(МассивФайлов,РезультирующийФайл);
УдалитьФайлы(ВременнаяПапка);
Иначе
УбитьВОМ(массив[0],РезультирующийФайл,ВременнаяПапка,МассивФайлов);
КонецЕсли;
КонецПроцедуры
В результате получается файл в кодировке "UTF-8 без BOM".
Примечание. понимаю, что через "ж", но если кто подскажет другой вариант это будет интересно со всех сторон.
А в остальном: кому нужно - пользуйтесь и экспериментируйте. Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
См. также
Универсальные функции 1С 8.3 1С:Документооборот Россия Платные (руб)
ДО+ — расширение конфигурации, в котором собран постоянно пополняемый набор из 33 востребованных доработок для 1С:Документооборот КОРП 3.0: согласование задач прямо из мессенджеров MAX и Telegram, отзыв согласования и исполнения, гибкие повторные круги, эскалация с точностью до минут, контроль исполнительской дисциплины, выгрузка вложений в ZIP и склейка PDF, реестр документов в Excel, проверка дублей контрагентов и регистрационных номеров. Каждая возможность активируется отдельным флажком в режиме предприятия — включается только то, что нужно конкретной организации. Список функций расширяется с каждым релизом — текущая версия 2.1.0. Режим AddOn: типовая конфигурация не модифицируется, обновления ДО ставятся штатно, дополнительные лицензии и внешние компоненты не требуются. Внедрение силами администратора — около часа.
30000 руб.
09.07.2026 1453 1 0
Загрузка и выгрузка в Excel Универсальные функции Разработчик 1С:Предприятие 8 Россия Бесплатно (free)
Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).
30.10.2025 8803 Abysswalker 11
Универсальные функции Работа с интерфейсом Разработчик 1С:Предприятие 8 Бесплатно (free)
Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.
14.05.2025 14583 DeerCven 16
Инструментарий разработчика Универсальные функции Запросы Разработчик 1С:Предприятие 8 1C:Бухгалтерия 1С:Бухгалтерия 3.0 1С:Зарплата и Управление Персоналом 3.x Бесплатно (free)
Внешняя обработка для создания запроса на основании табличных данных.
22.07.2024 11990 278 ixijixi 10
Универсальные функции Разработчик 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.
21.05.2024 68942 dimanich70 87
Универсальные функции Разработчик 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)
Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.
1 стартмани
18.03.2024 9336 7 John_d 13
Универсальные функции Разработчик Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.
12.02.2024 85989 atdonya 31
Универсальные функции Разработчик 1С:Предприятие 8 Бесплатно (free)
На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.
30.11.2023 13511 ke.92@mail.ru 18
например, так:
Попытка
Файл=СоздатьОбъект("ADODB.Stream");
Файл.Mode=3; // r/w
Файл.Type=1; //1-Binary, 2-Text
Файл.Open();
Файл.LoadFromFile(ИмяФайлаДанных);
Файл.Position=3;
ТекстБезБОМ=СоздатьОбъект("ADODB.Stream");
ТекстБезБОМ.Mode=3; // r/w
ТекстБезБОМ.Type=1; //1-Binary, 2-Text
ТекстБезБОМ.Open();
Файл.CopyTo(ТекстБезБОМ);
Файл.Close();
ТекстБезБОМ.SaveToFile(ИмяФайлаДанных,2);
ТекстБезБОМ.Close();
Исключение
ТекстОшибки=ОписаниеОшибки();
Сообщить(ТекстОшибки,"!");
Возврат;
КонецПопытки;
Показатьсинтаксис в примере 7-шный, но код применим для любой версии - 7.7, 8.х, главное, чтобы доступ к объекту ADODB.Stream был
Процедура УбитьВОМ(ИсходныйФайл,РезультирующийФайл)
Попытка
файл = Новый ComObject("ADODB.Stream");
файл.Mode = 3; // r/w
файл.Type = 1; //1-Binary, 2-Text
файл.Open();
файл.LoadFromFile(ИсходныйФайл);
файл.Position = 3;
текстБезБОМ = Новый ComObject("ADODB.Stream");
текстБезБОМ.Mode = 3; // r/w
текстБезБОМ.Type = 1; //1-Binary, 2-Text
текстБезБОМ.Open();
файл.CopyTo(текстБезБОМ);
файл.Close();
текстБезБОМ.SaveToFile(РезультирующийФайл,2);
текстБезБОМ.Close();
УдалитьФайлы(ИсходныйФайл);
Исключение
Сообщить(ОписаниеОшибки(),СтатусСообщения.Важное);
КонецПопытки;
КонецПроцедуры
1) получить двоичные данные из файла (как у вас)
2) преобразуем двоичные данные в строку с помощью ЗначениеИзСтрокиВнутр
3) анализируем формат, там не сложно, удаляем лишние переносы кареток (символ 10 вроде) // при желании могу описать подробнее
4) упаковываем поток обратно, получая двоичные данные
5) записываем в файл. Профит
1. при преобразовании "ЗначениеВСтрокуВнутр" 1с преобразует двоичные данные в формат base64, при этом длина строки становится больше размера иходного файла почти в полтора раза, это значит, что у нас уже текст не в кодировке UTF-8.
2. не совсем понятно: символы перевода строки (10) (возврат каретки - 13) обязательно удалять? а если это UTF-ный символ с кодом 10?
3. каким образом "упаковать поток обратно"? у объекта "ДвоичныеДанные" только 2 метода - "Размер()" и "Записать(ИмяФайла").
4. как записать в файл результат?
пробовал еще такой вариант:
бин = Новый ДвоичныеДанные(ИсходныйФайл);
бинСтрока = Base64Строка(бин);
новаяБинСтрока = Сред(бинСтрока,4);
бин = Base64Значение(новаяБинСтрока);
бин.Записать(РезультирующийФайл);
но там вообще ерунда получается.
может, примерчик рабочий есть?
Функция Текст2Base64(Текст, HEX=Ложь) Экспорт
// Описание:
Множитель1 = 256;
Множитель2 = 64;
СловарьСтрока = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456 789+/=";
Словарь = Новый Соответствие;
Для Сч=0 по 64 Цикл
Словарь.Вставить(Сч, Сред(СловарьСтрока, Сч+1, 1));
КонецЦикла;
Если HEX=Истина Тогда
К = 6;
Иначе
К = 3;
КонецЕсли;
ДлинаТекста = СтрДлина(Текст);
КоличествоЧастей = Цел(ДлинаТекста / К) + ?(ДлинаТекста%К=0, 0, 1);
Результат = "";
Для НомерЧасти = 1 По КоличествоЧастей Цикл
Часть = Сред(Текст, К*(НомерЧасти-1)+1, К);
Если HEX Тогда
Часть1 = ш(Сред(Часть, 1, 1));
Часть1 = ш(Сред(Часть, 2, 1)) + Часть1*16;
Часть2 = ш(Сред(Часть, 3, 1));
Часть2 = ш(Сред(Часть, 4, 1)) + Часть2*16;
Часть3 = ш(Сред(Часть, 5, 1));
Часть3 = ш(Сред(Часть, 6, 1)) + Часть3*16;
Иначе
Часть1 = КодСимвола(Сред(Часть, 1, 1));
Часть2 = КодСимвола(Сред(Часть, 2, 1));
Часть3 = КодСимвола(Сред(Часть, 3, 1));
КонецЕсли;
БольшоеЧисло = Часть1 * Множитель1 * Множитель1 + ?(Часть2=-1, 0, Часть2) * Множитель1 + ?(Часть3=-1, 0, Часть3);
Часть4_ = БольшоеЧисло % Множитель2;
БольшоеЧисло = (БольшоеЧисло-Часть4_) / Множитель2;
Часть3_ = БольшоеЧисло % Множитель2;
БольшоеЧисло = (БольшоеЧисло-Часть3_) / Множитель2;
Часть2_ = БольшоеЧисло % Множитель2;
БольшоеЧисло = (БольшоеЧисло-Часть2_) / Множитель2;
Часть1_ = БольшоеЧисло;
Если СтрДлина(Часть)=1*?(HEX, 2, 1) Тогда
Часть3_ = 64;
Часть4_ = 64;
ИначеЕсли СтрДлина(Часть)=2*?(HEX, 2, 1) Тогда
Часть4_ = 64;
КонецЕсли;
Результат = Результат + Словарь.Получить(Часть1_) + Словарь.Получить(Часть2_) + Словарь.Получить(Часть3_) + Словарь.Получить(Часть4_);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция Ш(С) Экспорт
Возврат ?(С>="0" и С<="9", КодСимвола(С)-КодСимвола("0"),
?(С>="A" и С<="F", КодСимвола(С)-КодСимвола("A")+10, -1));
КонецФункции
Процедура Text2Base64(Текст64)
з = "{""#"",87126200-3e98-44e0-b931-ccb1d7edc497,
|{1,
|{#base64:"+Текст64+"}
|}
|}";
д = ЗначениеИзСтрокиВнутр(з);
Сообщить(д);
д.Записать("e:\1.f");
КонецПроцедуры
Процедура Base642Text(Текст64)
ф = "e:\2.txt";
норм = "{""#"",87126200-3e98-44e0-b931-ccb1d7edc497,
|{1,
|{#base64:"+Текст2Base64(Текст64, Истина)+"}
|}
|}";
д = ЗначениеИзСтрокиВнутр(норм);
д.Записать(ф);
Сообщить(д);
КонецПроцедуры
ПоказатьТолько у вас ошибка.
Вот рабочий код:
файлЛог=ПолучитьИмяВременногоФайла(".txt");
Текст.Записать(файлЛог);
// теперь нужно получить файл без BOM
ОБ_ДД=Новый ДвоичныеДанные(файлЛог);
Стр_Base64=Base64Строка(ОБ_ДД);
ОБ_ДД=Base64Значение(Сред(Стр_Base64,5));
ОБ_ДД.Записать(файлЛог);Использовал в
В 8.3 не проверял еще, но думаю должно сработать.
УдалитьФайлы(ИмяФайла); // надо убедиться, что файл не существует, т.к. если он существует, то данные добавятся в конец файла
ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(МояСтрока);
ЗТ.Закрыть();
И никаких извращений...
ЗТ = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
ЗТ.Закрыть();
ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(Данные);
ЗТ.Закрыть();
Попробовал твой метод, и выяснил, что за вредные символы отвечает параметр "Дописывать" в конструкторе "ЗаписьТекста"
в общем получилось так:
УдалитьФайлы(имяФайлаОтправки); это да, это обязательно
ЗаписьТекста = Новый ЗаписьТекста(имяФайлаОтправки,КодировкаТекста.UTF8,,Истина,Символы.ПС);
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""goods.xml""");
ЗаписьТекста.ЗаписатьСтроку("Content-Type: text/xml");
ЗаписьТекста.ЗаписатьСтроку("");
и ниже пишем содержимое XML файла
СПАСИБО
Поимел проблему. У меня был тестовый файл и файл сгенеренный 1С, с виду абсолютно одинаковые. Разница в размере в 2 байта. Хеш программа выдавала разный. Оказалось что по умолчанию 1С указывается символ перевода строки и при создании файла и при добавлении строки. Указал в обоих местах в качестве символа "" и все пошло. Использовал много идей из этого поста. Возможно кому то будет полезен полный код.
Функция ПолучитьХЭШГОСТ(СтрокаНаВход)
// очистили входящий файл
УдалитьФайлы(КаталогВременныхФайлов()+"in.txt");
ТекстIn = Новый ЗаписьТекста(КаталогВременныхФайлов()+"in.txt", КодировкаТекста.UTF8,"", Ложь,);
ТекстIn.ЗаписатьСтроку(Строка(СокрЛП(ВРЕГ(ВходящиеДанные))));
ТекстIn.Закрыть();
// обрезаем ВОМ
ОБ_ДД=Новый ДвоичныеДанные(КаталогВременныхФайлов()+"in.txt");
Стр_Base64=Base64Строка(ОБ_ДД);
ОБ_ДД=Base64Значение(Сред(Стр_Base64,5));
ОБ_ДД.Записать(КаталогВременныхФайлов()+"in.txt");
// очистили выходной файл
УдалитьФайлы(КаталогВременныхФайлов()+"out.txt");
ТекстOut = Новый ЗаписьТекста(КаталогВременныхФайлов()+"out.txt", КодировкаТекста.UTF8,,Ложь,);
ТекстOut.Закрыть();
//запустили приложение хеширования
ЗапуститьПриложение(Строка(ИмяФайла)+" --gost-cryptopro "+КаталогВременныхФайлов()+"in.txt"+" "+"--output="+КаталогВременныхФайлов()+"out.txt",,Истина,);
//прочитали из выходного файла результат
Текст = Новый ЧтениеТекста(КаталогВременныхФайлов()+"out.txt", КодировкаТекста.UTF8);
Стр = Текст.ПрочитатьСтроку(""); //при создании файла перевод строки убрали,при чтении тоже убрали, то есть читаем весь файл как строку
Стр = СтрЗаменить(Стр,Строка(КаталогВременныхФайлов()+"in.txt"),"");
РезультатХеширования = Врег(Стр);
Возврат РезультатХеширования;
КонецФункции
////создаем сам файл
СписокЭкспорт = Новый ТекстовыйДокумент;
СписокЭкспорт.ДобавитьСтроку(ПерваяСтрокаФайла); ////в цикле добавляем все что надо
СписокЭкспорт.Записать(ИмяФайлаЭкспортаCSV,КодировкаТекста.UTF8); //// Где "ИмяФайлаЭкспортаCSV" полный путь к файлу
////меняем в готовом файле кодировку "с BOM" на "без BOM"
КонвертируемыйФайл = Новый ДвоичныеДанные(ИмяФайлаЭкспортаCSV);
Строка64=Base64Строка(КонвертируемыйФайл);
Строка64=Прав(Строка64,СтрДлина(Строка64)-4);
ДляЗаписиВФайл=Base64Значение(Строка64);
ДляЗаписиВФайл.Записать(ИмяФайлаЭкспортаCSV); Показать
ФП = Новый ФайловыйПоток(ИмяФайлаИсходного,РежимОткрытияФайла.СоздатьНовый,ДоступКФайлу.ЧтениеИЗапись);
Текст = Новый ЗаписьТекста(ФП,,, Истина, Ложь);//Последний параметр самый важный
Текст.Записать(СтрокаДанных);
Текст.Закрыть();
ФП.Закрыть();
Текст = Новый ЗаписьТекста(ФП,КодировкаТекста.UTF8,, , Ложь);//Предпоследний параметр не нужен, надо так ;)Тип: Булево.
Если в начало потока требуется записать метку порядка байтов (BOM) для используемой кодировки текста, то данный параметр должен иметь значение Истина.
Значение по умолчанию: Ложь.
ВременныйФайл = Новый ЗаписьТекста(ИмяФайла);
ВременныйФайл.Записать(ТекстJSON);
ВременныйФайл.Закрыть();
Надо через поток вот так
Тело = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(Тело);
ЗаписьДанных.ЗаписатьСтроку(ТекстJSON);
ЗаписьДанных.Закрыть();
ДанныеТела = Тело.ЗакрытьИПолучитьДвоичныеДанные();
ДанныеТела.Записать(ИмяФайла);
ПоказатьПо имени файла
Синтаксис:
Новый ЗаписьТекста(<ИмяФайла>, <Кодировка>, <РазделительСтрок>, <Дописывать>, <КонвертируемыйРазделительСтрок>)
Параметры:
<ИмяФайла> (обязательный)
Тип: Строка.
Имя текстового файла для записи.
<Кодировка> (необязательный)
Тип: КодировкаТекста, Строка.
Кодировка записываемого текста (согласована с текстовым документом).
Кодировка может быть задана как в виде значения перечисления КодировкаТекста, так и в виде строки с указанием названия кодировки.
Поддерживаемые кодировки:
UTF-8
UTF-16
UTF-16BE
UTF-16LE
ISO-8859-1
US-ASCII
gb18030
iso-8859-2
iso-8859-3
iso-8859-4
iso-8859-5
iso-8859-6
iso-8859-7
iso-8859-8
iso-8859-9
iso-8859-13
iso-8859-15
Shift_JIS
EUC-JP
Big5
Big5-HKSCS
GBK
GB2312
GB_2312-80
EUC-KR
KSC_5601
windows-949
windows-874
cp866
KOI8-R
KOI8-U
windows-1250
windows-1251
windows-1252
windows-1253
windows-1254
windows-1255
windows-1256
windows-1257
windows-1258
macintosh
x-mac-cyrillic
ISO-2022-JP
ISO-2022-KR
ISO-2022-CN
ISO-2022-CN-EXT
HZ-GB-2312
Значение по умолчанию: UTF8.
<РазделительСтрок> (необязательный)
Тип: Строка.
Символ разделителя строк в записываемом файле.
Значение по умолчанию: ПС.
<Дописывать> (необязательный)
Тип: Булево.
Если параметр принимает значение Истина, то содержимое файла сохраняется, если файл уже существует. Если файла не существует, создается новый с именем, указанным в первом параметре конструктора.
Значение по умолчанию: Ложь.
<КонвертируемыйРазделительСтрок> (необязательный)
Тип: Строка.
Определяет разделение строк в файле для конвертации в стандартный перевод строк ПС.
Значение по умолчанию: ВК + ПС.
Описание:
Открывает текстовый файл для записи. Аналогичен методу Открыть.
УстановитьТелоИзСтроки (SetBodyFromString)
Доступен, начиная с версии 8.2.
Синтаксис:
УстановитьТелоИзСтроки(<ТелоКакСтрока>, <Кодировка>, <ИспользоватьBOM>)
Параметры:
<ТелоКакСтрока> (обязательный)
Тип: Строка.
Содержит тело запроса в виде строки.
<Кодировка> (необязательный)
Тип: КодировкаТекста, Строка.
Определяет кодировку, в которой будет отправлен HTTP-запрос. Если параметр не задан, то тело отправляется в кодировке UTF8.
Установка этого параметра не вызывает автоматической установки соответствующего HTTP-заголовка.
Кодировка может быть задана как в виде значения перечисления КодировкаТекста, так и в виде строки с указанием названия кодировки.
В веб-клиенте параметр игнорируется. Строка интерпретируется в кодировке UTF-8.
Поддерживаемые названия кодировок:
UTF-8
UTF-16
UTF-16BE
UTF-16LE
ISO-8859-1
US-ASCII
gb18030
iso-8859-2
iso-8859-3
iso-8859-4
iso-8859-5
iso-8859-6
iso-8859-7
iso-8859-8
iso-8859-9
iso-8859-13
iso-8859-15
Shift_JIS
EUC-JP
Big5
Big5-HKSCS
GBK
GB2312
GB_2312-80
EUC-KR
KSC_5601
windows-949
windows-874
cp866
KOI8-R
KOI8-U
windows-1250
windows-1251
windows-1252
windows-1253
windows-1254
windows-1255
windows-1256
windows-1257
windows-1258
macintosh
x-mac-cyrillic
ISO-2022-JP
ISO-2022-KR
ISO-2022-CN
ISO-2022-CN-EXT
HZ-GB-2312
.
<ИспользоватьBOM> (необязательный)
Тип: ИспользованиеByteOrderMark.
Использовать метку порядка байтов (BOM) для кодировок, которые ее поддерживают: UTF-8, UTF-16 и др.
В режиме совместимости конфигурации значение по умолчанию - Использовать.
В веб-клиенте параметр игнорируется.
Значение по умолчанию: Авто.
Описание:
Устанавливает тело запроса из строки.
Доступность:
Тонкий клиент, мобильный клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение (клиент), мобильное приложение (сервер), мобильный автономный сервер.
Примечание:
В веб-клиенте параметры <Кодировка>, <ИспользоватьBOM> игнорируются. Строка интерпретируется в кодировке utf-8.
Использование в версии:
Доступен, начиная с версии 8.2.
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 137454
Создание 26.05.12 13:44
Обновление 26.05.12 13:44
Просмотры 58115
Загрузки 0
Рейтинг
16
Комментарии 39
Код открыт Не указано
Рубрики Универсальные функции
Кому Разработчик
Тип файла Нет файла
Платформа 1С:Предприятие 8
Конфигурация 1C:Бухгалтерия
Операционная система Не имеет значения
Страна Россия
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Бесплатно (free)