gifts2017

Чтение/Запись документа Excel 2007 без офиса, без внешних компонент. (с примером для 7.7, 8.1 и 8.2 на управляемых формах)

Опубликовал Василий Демидов (Душелов) в раздел Программирование - Практика программирования

Чтение/запись документ Excel 2007 без установленного Excel'а, без внешних компонент, исключительно средствами 1С (7.7, 8.1, 8.2 на управляемых формах).

Написано в ознакомительных целях, по аналогии с http://infostart.ru/projects/2365/

Использование (1С 8.x): вставляете обработку в конфигурацию и используете ее методы:

Процедура ОткрытьФайлЭкзекль2007(ПутьКФайлу)
    Экзель = Обработки.Excel2007.Создать();
 
    Если НЕ Экзель.ОткрытьФайл(ПутьКФайлу) Тогда
        Предупреждение("Файл " + ПутьКФайлу + " не открыт!");
        Возврат;
    КонецЕсли;
 
    Если НЕ Экзель.ОткрытьЛист(1) Тогда
        Предупреждение("Лист 1 не открыт!");
        Возврат;
    КонецЕсли;
 
    Сообщить("Количество строк: " + Экзель.Лист.Количество());
    Сообщить("Количество колонок: " + Экзель.Лист.Колонки.Количество());
КонецПроцедуры

Процедура СоздатьФайлЭкзель2007(ПутьКФайлу)
    //заполняем ТЗ
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("К1");
    ТЗ.Колонки.Добавить("К2");
 
    Стр = ТЗ.Добавить();
    Стр.К1 = "Номенклатура";
    Стр.К2 = "Количество";
 
    Стр = ТЗ.Добавить();
    Стр.К1 = "Хлеб";
    Стр.К2 = 10;
 
    Стр = ТЗ.Добавить();
    Стр.К1 = "Мясо";
    Стр.К2 = 14;
 
    //сохраняем тз в экзель
    Экзель = Обработки.Excel2007.Создать();
    Экзель.Лист = ТЗ;
    Экзель.Записать(ПутьКФайлу);
 
КонецПроцедуры

Использование (1С 7.7): добавляете из демо-базы все из глобального модуля в свой, файл шаблона кладете в папку с конфигурацией и используете по примеру:

Процедура ОткрытьФайлЭкзекль2007(ПутьКФайлу)
    Если экзель_ОткрытьФайл(ПутьКФайлу) = 0 Тогда
        Предупреждение("Файл " + ПутьКФайлу + " не открыт!");
        Возврат;
    КонецЕсли;
 
    Если экзель_ОткрытьЛист(1) = 0 Тогда
        Предупреждение("Лист 1 не открыт!");
        Возврат;
    КонецЕсли;
 
    Сообщить("Количество строк: " + экзель_Лист.КоличествоСтрок());
    Сообщить("Количество колонок: " + экзель_Лист.КоличествоКолонок());
    Сообщить("***");
 
    //выведем 1 строку
    Для сч = 1 По экзель_Лист.КоличествоКолонок() Цикл
        Сообщить(экзель_Лист.ПолучитьЗначение(1, сч));
    КонецЦикла;
КонецПроцедуры
//*******************************************
Процедура СоздатьФайлЭкзель2007(ПутьКФайлу)
    //заполняем ТЗ
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("К1");
    ТЗ.НоваяКолонка("К2");
 
    ТЗ.НоваяСтрока();
    ТЗ.К1 = "Номенклатура";
    ТЗ.К2 = "Количество";
 
    ТЗ.НоваяСтрока();
    ТЗ.К1 = "Хлеб";
    ТЗ.К2 = 10;
 
    ТЗ.НоваяСтрока();
    ТЗ.К1 = "Мясо";
    ТЗ.К2 = 14;
 
    //сохраняем тз в экзель
    экзель_Лист = ТЗ;
    Если экзель_Записать(ПутьКФайлу) = 1 Тогда
        Сообщить("Создан " + ПутьКФайлу);
        ЗапуститьПриложение(ПутьКФайлу);
    КонецЕсли;
КонецПроцедуры

Скачать файлы

Наименование Файл Версия Размер
Обработка для 8.1 и 8.2 2231
.zip 29,08Kb
20.01.10
2231
.zip 29,08Kb Бесплатно
Конфигурация для 1С 7.7 818
.1235567370 37,10Kb
25.09.09
818
.1235567370 37,10Kb Бесплатно

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Василий Демидов (Душелов) 24.02.09 17:10
Свойство "Лист" у обработки - это таблица значений.
2. Василий Демидов (Душелов) 24.02.09 17:14
Собственно код довольно прост, идея, думаю, ясна ;)
3. Сергей Кучеров (СергейКа) 24.02.09 17:40
+ адназначна. Идея супер.
4. Александр Шишкин (Шёпот теней) 24.02.09 17:51
Душелов... НУуу..., блин, ТЫ ДАёШЬ...

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


воОотВеДь...
5. Василий Демидов (Душелов) 24.02.09 17:54
Для 7-ки сделаю, наверное, вечером обработочку... Но сразу оговорюсь, понадобится либо ВК для архивирования, либо какой-либо архиватор, ибо сама платформа с зипами работать не умеет.
6. Александр Шишкин (Шёпот теней) 24.02.09 17:56
гы... уговорил... поставил в твоих других работах...

всё равно за всё заслуженно....!!! удачи во всём....!!!!

воооот....ведь....
7. Алексей Коробов (WiseSnake) 24.02.09 17:59
8. Сhe Burashka (CheBurator) 24.02.09 20:41
> ибо сама платформа с зипами работать не умеет.
если считать, что работаем на хрюне и выше - то можно юзать встроенный в винды зиповщик
9. Василий Демидов (Душелов) 24.02.09 20:45
10. Сhe Burashka (CheBurator) 24.02.09 20:47
встроенный!!! пошарь на мисте! там Абрахамс показывал ккак делать.. если не найдешь стукнись - у мну есть в загашнике где-то... просто ща работы срочная дофига
11. Сергей (СЫРОЖА) 25.02.09 07:20
Не понял, причем тут архиватор? И вообще, если это только идея,
причем тут привязка к 2007-му экзелю?
12. Василий Демидов (Душелов) 25.02.09 09:12
(11) :))))) Мои "идеи" отличаются от "идей" некоторых других "коллег" по инфостарту.

А посмотреть разработку?
13. Сергей (seermak) 25.02.09 09:20
Вопрос на расширение кругозора): 1.а зачем в шаблоне заполнено поле значением "aha". 2. а как сделать так, чтобы сохранилось форматирование(допустим объединение ячеек). Узнал много нового о ".xlsx". За это отдельное спасибо!)))
14. Василий Демидов (Душелов) 25.02.09 09:29
(13) 1. Да просто... Только, чтобы экзель создал все нужные файлы для шаблона, на всякий случай.
2. По поводу форматирования - это уже надо копать в сторону других файлов, отвечающих за оформление. Как я делаю - беру файл, объединяю, к примеру, ячейки, сохраняю и смотрю изменения.
16. Василий Демидов (Душелов) 25.02.09 09:46
(15) Спасибо, я уже разобрался... ;)
Вот только метод Темп.CopyHere(Файл), открывает диалог и предлагает заменить файлы, если такие существуют. И на 2 параметр (8, 16 и т.д.) не реагирует никак. Но это я поборю :)
17. baa (baa) 25.02.09 10:00
Душелов, я на тебя отдельную папку завел в каталоге для скачаных файлов 1С. Так сказать есть 7.7, есть 8.1 и есть отдельный проект "Душелов" :) Однозначно молодец.
18. Василий Демидов (Душелов) 25.02.09 16:13
Упарился я с вашей 7-кой... ;) Давно не писал ничего толкового...
Вообщем... В 7-ке тоже, никаких ВК.
19. Василий Демидов (Душелов) 25.02.09 16:15
Как бы глюки какие-то возможно в 7-ке, т.к. работа с архивами и xml тоже написаны на языке платформы (мисте привет ;)).
20. Трактор Трактор (Трактор) 25.02.09 19:44
Вах, молодец! Скачивать не стал. Просто буду знать что такая разработка есть.
21. Трактор Трактор (Трактор) 25.02.09 22:36
Не удержался. Скачал. Красиво. Спасибо.
22. Игорь Белышев (biv75) 26.02.09 14:36
Супер! Плюсую однозначно
23. minimax (minimaxpo) 26.02.09 14:37
Гут, мне нравится ход ваших мыслей.
24. Tregi (Vitalk) 03.03.09 14:50
В принципе, хорошая вешь! Кому то да и пригодится!
Только небольшая помарочка в Excel2007. Когда пустой путь к файлу и при нажатии на "Открыть" пишет: Преобразование значения к типу Число не может быть выполнено ФайлЛиста = ВременныйКаталог + "\xl\worksheets\sheet" + НомерЛиста + ".xml". Просто не определена переменная "ВременныйКаталог"!
25. Alex P (alexmif) 17.04.09 12:14
Скачал! Не удержался. Интересная мысль... Теперь не забыть куда скачал.
+ однозначно, хотя мона и +++++.
26. ac86 (Aleanza) 09.05.09 13:28
Если есть пустое поле в таблице значений тип "Строка" оно глючит.
28. ac86 (Aleanza) 09.05.09 13:28
29. ac86 (Aleanza) 09.05.09 13:34
А еще оно не сохраняет заголовки, очень не удобно :(
30. Павел Городилов (bxz) 23.08.09 21:13
Возникла проблема при записи таблицы значений с количеством строк больше 999 решилась заменой функции ПолучитьИмяСтроки(а) на:
Функция ПолучитьИмяСтроки(а)
Возврат Формат(а + 1,"ЧГ=");
КонецФункции
но это все не важно )) за идею ++++++++
31. dushelov (Душелов) 20.01.10 12:34
(26), (30) поправил

Добавил версию для 8.2 на управляемых формах для тонкого клиента.
32. Руслан Батршин (RuslanBZ) 10.03.10 13:50
В версии 8.2 при нажатии на открыть ругается в функции ОткрытьЛист(НомерЛиста)

{ВнешняяОбработка.Excel2007.МодульОбъекта(64)}: Значение не является значением объектного типа (Строки)
Для Каждого Стр Из Колонки.Строки Цикл
33. Андрей Д. (detec) 25.05.10 11:02
Идея очень красивая. Но для произвольных файлов, редактируемых пользователями, я бы не советовал. Взял 3 файла. Два выгружены из PL/SQL Developer, один сделан из пользовательского в Office 2010. В результате открылся только 1. Остальные ругнулись .

{ВнешняяОбработка.Excel2007(63)}: Значение не является значением объектного типа (Строки)
Для сч = 0 По Колонки.Строки.Количество() - 1 Цикл


{ВнешняяОбработка.Excel2007(93)}: Поле объекта не обнаружено (F)
НоваяСтрока[МассивБукв[ИндексСтроки]] = ЗначениеЯчейки;


34. ntl 31.05.10 18:32
При сохранении ТЗ в которой были пустые ячейки, обработка выдает ошибку.

{ВнешняяОбработка.Excel2007(266)}: Ошибка при вызове метода контекста (Индекс): Несоответствие типов (параметр номер '1')
ЗначЯчейки = СписокСтрок.Индекс(Элем);
по причине:
Несоответствие типов (параметр номер '1')
35. ntl 31.05.10 20:41
Не помогло. Все равно дает ошибку:
{ВнешняяОбработка.Excel2007(266)}: Ошибка при вызове метода контекста (Индекс): Несоответствие типов (параметр номер '1')
ЗначЯчейки = СписокСтрок.Индекс(Элем);
по причине:
Несоответствие типов (параметр номер '1')
36. ntl 31.05.10 20:59
Интересный момент. Пробую сохранить ТЗ размером 14 на 710 ячеек.
1. Выдает ошибки при пустых ячейках. Если ячейка не текст, а большое поле типа Memo.
2. Где то с 283 строки в ячейки начинает подставлять числа, начиная с 1000. и пошел часть ячеек записывает нормально а потом оп и 1001, часть ячеек нормально, 1002 и т д.
Хотя вторая ошибка это возможно результат исправления первой ) Такой я программист )))
37. ntl 31.05.10 21:27
Да так и есть ошибка №2 из п. (36) это результат моих фокусов.
Но 2 момента остались:
1. Если есть пустое большое поле, то она выдает ошибку
2. Дата при открытии получается в формате DD.MM. YYYY обрезается. При этом если стр.252: ЗначЯчейки = Лист.Получить(иСтр).Получить(иКол); заменить на ЗначЯчейки = Строка(Лист.Получить(иСтр).Получить(иКол)); то эта ошибка решается. Но появляются другие :)
Не подумайте что я жалуюсь. Идея супер. Буду искать причины и править. Но если кто быстрее меня сообразит, дайте знать. т.к. искать я могу очень долго )))
38. Александр Цегельников (markers) 17.06.10 08:00
Подтверждаю проблему с "сдвигом" ячеек при наличии пустых ячеек, решил её по своему, но потом полез сюда, и заменил всё на новый код, начал матюгатся как в (33) Вернул старый код с своей правкой, Автору боооольшое спасибо! Надеюсь когда вернётся сможет нам помочь.

ADD: Кстати старый код работает нормально и быстро, интересно, новый код быстрей?
39. Александр Цегельников (markers) 17.06.10 09:03
Кому нужно получить список листов и кто не догадался как это сделать, даю функцию:
Функция Excel2007СписокЛистов(ВременныйКаталог);
	Листы = НайтиФайлы(ВременныйКаталог + "\xl\worksheets\", "sheet*.xml");
	Возврат Листы.Количество();
КонецФункции	

40. dushelov (Душелов) 17.06.10 11:51
Выложите сюда проблемный файл, посмотрим.
41. Александр Цегельников (markers) 17.06.10 12:30
(40) Ловите, простой прайс правда сделанный в 2003-ем и сконвертированный в 2007-й
Там 3 листа, 2-й пустой, в моём варианте они обрабатываются все вместе
Прикрепленные файлы:
price_test.xlsx
42. Александр Цегельников (markers) 22.06.10 06:00
43. Игорь Степанов (webstep) 25.06.10 17:55
если в файле excel данные не стоят стройными рядами, а "гуляют" по полю, то при работе алгоритма возникает ошибка потому что "мелкософтмасдай" почему то в "cols" пишет не все колонки. Пришлось ориентироваться на "dimension". Соответственно в функции ОткрытьЛист заменил код
//создаем колонки
Колонки = ДеревоДанных.Строки.Найти("cols", "Объект", Истина);
сч = 0;	
Для Каждого Стр Из Колонки.Строки Цикл
 Если Стр.Объект <> "col" Тогда
 Продолжить;
 КонецЕсли;
		
 Лист.Колонки.Добавить(МассивБукв[сч]);
 сч = сч + 1;
 КонецЦикла;
...Показать Скрыть

на
//создаем колонки
Колонки = ДеревоДанных.Строки.Найти("dimension", "Объект", Истина);
Счетчик = 0;	
Для Каждого Стр Из Колонки.Строки Цикл
 Если Стр.Объект = "ref" Тогда
 Диапозон = Стр.Значение; 
 //поиск максимального значения колонки
 Счетчик=МассивБукв.Количество();
 Пока Счетчик>0 Цикл 
 Счетчик = Счетчик - 1;
 Если Найти(Диапозон, МассивБукв[Счетчик])>0 Тогда
 Для Индекс=0 По Счетчик Цикл					
 Лист.Колонки.Добавить(МассивБукв[Индекс]);
 КонецЦикла;	
 Счетчик = 0;
 КонецЕсли;	
 КонецЦикла;
 Прервать;
 КонецЕсли;
КонецЦикла;
...Показать Скрыть

теперь колонки формирует правильно.
44. Игорь Степанов (webstep) 28.06.10 11:34
проблема сдвига ячеек...

удалил
ИндексСтроки = -1;

и, ориентируясь на значение в "r", заменил:
ИндексСтроки = ИндексСтроки + 1;

на
 //поиск колонки
 СтрЗначение = Колонка.Строки.Найти("r", "Объект");
 Если СтрЗначение <> Неопределено Тогда
 ИмяКолонки = СтрЗначение.Значение;
 КонецЕсли;
 ИндексСтроки = Неопределено;
 Счетчик = МассивБукв.Количество();
 Пока Счетчик>0 Цикл 
 Счетчик = Счетчик - 1;
 Если Найти(ИмяКолонки, МассивБукв[Счетчик])>0 Тогда
 ИндексСтроки = Счетчик;
 Счетчик = 0;
 КонецЕсли;	
 КонецЦикла;
.........................
...Показать Скрыть

проблема решена

extralook; gluker3; +2 Ответить
45. Игорь Степанов (webstep) 28.06.10 11:38
да, все это в функции ОткрытьЛист модуля обработки

прошу не пинать ногами - на больших таблицах код может работать медленно, но это уже менять МассивБукв на что-то иное...

и вот еще что... обработка благодаря этому самому массиву букв расчитана на не очень большие таблицы, но я на всякий случай предусмотрел его расширение и на двухбуквенные колонки, поэтому поиск ведется от конца к началу, а не наоборот.

кстати, как здесь можно свой комментарий удалить? вот еще проблема...
46. Игорь Степанов (webstep) 28.06.10 12:34
Прошу прощения автора, я на основании его обработки создал для себя функцию, которая читает лист из файла и возвращает таблицу значений.

Функция ПолучитьЛистEXCEL_XML(ИмяФайлаExcel, НомерЛиста=1) Экспорт
	
	ИмяФайла = СокрЛП(ИмяФайлаExcel);
	Если Прав(НРег(ИмяФайла),4)<>".xlsx" Тогда 
		//ошибка
	КонецЕсли;
	
	пФайл = Новый Файл(ИмяФайла);
	Если Не пФайл.Существует() Тогда
		//ошибка
	КонецЕсли;
	
	СписокСтрок = Новый СписокЗначений;
	
	ВременныйКаталог = КаталогВременныхФайлов() + "NightReg";
	УдалитьФайлы(ВременныйКаталог);
	
	Зип = Новый ЧтениеZipФайла;
	Зип.Открыть(ИмяФайла);
	Зип.ИзвлечьВсе(ВременныйКаталог, РежимВосстановленияПутейФайловZIP.Восстанавливать);
	
	ФайлСтрок = ВременныйКаталог + "\xl\sharedStrings.xml";
	
	хмл = Новый ЧтениеXML;
	хмл.ОткрытьФайл(ФайлСтрок);
	
	Пока хмл.Прочитать() Цикл
		Если хмл.ТипУзла = ТипУзлаXML.Текст Тогда
			СписокСтрок.Добавить(хмл.Значение);
		КонецЕсли;
	КонецЦикла;
	
	хмл.Закрыть();
	
	ФайлЛиста = ВременныйКаталог + "\xl\worksheets\sheet"+НомерЛиста+".xml";
	Файл = Новый Файл(ФайлЛиста);
	Если НЕ Файл.Существует() Тогда
		//ошибка
	КонецЕсли;
	
	МассивБукв = Новый Массив;
	МассивБукв.Добавить("A");
	МассивБукв.Добавить("B");
	МассивБукв.Добавить("C");
	МассивБукв.Добавить("D");
	МассивБукв.Добавить("E");
	МассивБукв.Добавить("F");
	МассивБукв.Добавить("G");
	МассивБукв.Добавить("H");
	МассивБукв.Добавить("I");
	МассивБукв.Добавить("J");
	МассивБукв.Добавить("K");
	МассивБукв.Добавить("L");
	МассивБукв.Добавить("M");
	МассивБукв.Добавить("N");
	МассивБукв.Добавить("O");
	МассивБукв.Добавить("P");
	МассивБукв.Добавить("Q");
	МассивБукв.Добавить("R");
	МассивБукв.Добавить("S");
	МассивБукв.Добавить("T");
	МассивБукв.Добавить("U");
	МассивБукв.Добавить("V");
	МассивБукв.Добавить("W");
	МассивБукв.Добавить("X");
	МассивБукв.Добавить("Y");
	МассивБукв.Добавить("Z"); 
	//здесь можно расширить двухбуквенными значениями
	
	ДеревоДанных = Новый ДеревоЗначений;
	ДеревоДанных.Колонки.Добавить("Объект");
	ДеревоДанных.Колонки.Добавить("Значение");
	
	ЧтениеXML = Новый ЧтениеXML;
	ЧтениеXML.ОткрытьФайл(Файл);
	
	ТекЭлемент = Неопределено;
	ТекБаза = Неопределено;
	
	Пока ЧтениеXML.Прочитать() Цикл
		Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			РежимЗагрузки = ЧтениеXML.Имя;
			
			Если ТекЭлемент = Неопределено Тогда
				ТекЭлемент = ДеревоДанных.Строки.Добавить();
				ТекЭлемент.Объект = РежимЗагрузки;
			Иначе
				ТекЭлемент = ТекЭлемент.Строки.Добавить();
				ТекЭлемент.Объект = РежимЗагрузки;					
			КонецЕсли;
			
		ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
			Если ТекЭлемент = Неопределено Тогда
				ТекЭлемент = Неопределено;
			Иначе
				ТекЭлемент = ТекЭлемент.Родитель;
			КонецЕсли;
		ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
			ТекЭлемент.Значение = ЧтениеXML.Значение;
		КонецЕсли;
		
		Для сч = 0 По ЧтениеXML.КоличествоАтрибутов() - 1 Цикл
			Стр = ТекЭлемент.Строки.Добавить();
			Стр.Объект = ЧтениеXML.ИмяАтрибута(сч);
			Стр.Значение = ЧтениеXML.ЗначениеАтрибута(сч);
		КонецЦикла;
	КонецЦикла;
	
	ЧтениеXML.Закрыть();
	
	Лист = Новый ТаблицаЗначений;
	
	//создаем колонки
	Колонки = ДеревоДанных.Строки.Найти("dimension", "Объект", Истина);
	Счетчик = 0;	
	Для Каждого Стр Из Колонки.Строки Цикл
		Если Стр.Объект = "ref" Тогда
			Диапазон = Стр.Значение; 
			
			//поиск максимального значения колонки
			Счетчик=МассивБукв.Количество();
			Пока Счетчик>0 Цикл 
				Счетчик = Счетчик - 1;
				Если Найти(Диапазон, МассивБукв[Счетчик])>0 Тогда
					Для Индекс=0 По Счетчик Цикл					
						Лист.Колонки.Добавить(МассивБукв[Индекс]);
					КонецЦикла;	
					Счетчик = 0;
				КонецЕсли;	
			КонецЦикла;
			
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	//читаем строки
	СтрСтрок = ДеревоДанных.Строки.Найти("sheetData", "Объект", Истина);
	Для Каждого Строка Из СтрСтрок.Строки Цикл
		НоваяСтрока = Лист.Добавить();
		
		Для Каждого Колонка Из Строка.Строки Цикл
			Если Колонка.Объект <> "c" Тогда
				Продолжить;
			КонецЕсли;
			
			//поиск колонки
			СтрЗначение = Колонка.Строки.Найти("r", "Объект");
			Если СтрЗначение <> Неопределено Тогда
				ИмяКолонки = СтрЗначение.Значение;
			КонецЕсли;
			ИндексСтроки = Неопределено;
			Счетчик = МассивБукв.Количество();
			Пока Счетчик>0 Цикл 
				Счетчик = Счетчик - 1;
				Если Найти(ИмяКолонки, МассивБукв[Счетчик])>0 Тогда
					ИндексСтроки = Счетчик;
					Счетчик = 0;
				КонецЕсли;	
			КонецЦикла;
			
			ЗначениеЯчейки = Неопределено;
			
			СтрЗначение = Колонка.Строки.Найти("v", "Объект");
			Если СтрЗначение <> Неопределено Тогда
				ЗначениеЯчейки = СтрЗначение.Значение;
			КонецЕсли;
			
			СтрЗначение = Колонка.Строки.Найти("t", "Объект");
			Если СтрЗначение <> Неопределено И СтрЗначение.Значение = "s" И ЗначениеЯчейки <> Неопределено Тогда
				ЗначениеЯчейки = СписокСтрок.Получить(Число(ЗначениеЯчейки)).Значение;
			КонецЕсли;
			
			НоваяСтрока[МассивБукв[ИндексСтроки]] = ЗначениеЯчейки;
		КонецЦикла;
	КонецЦикла;
	
	Возврат Лист;
КонецФункции
...Показать Скрыть
kazann; artbear; +2 Ответить
47. Игорь Степанов (webstep) 28.06.10 17:36
да вот еще что до меня дошло - пустые строки тоже исчезают, нужно еще думать... впрочем для многих это не будет такой уж потерей :)

и еще у меня в коде (46) тоже закралась ошибочка:
Если Прав(НРег(ИмяФайла),4)<>".xlsx" Тогда 

тут циферку 5 надо :oops:
48. Артур Аюханов (artbear) 27.09.10 13:39
(31) Вчера скачал версию для 8.1
В нем (26) "Если есть пустое поле в таблице значений тип "Строка" оно глючит." так и не исправлено.
49. Артур Аюханов (artbear) 27.09.10 14:03
Также есть ошибка при записи листа, если у числа в таблице есть дробная часть :(
Запись проходит успешно, но при попытке открыть полученный файл в Офис 2007 выдается ошибка о невозможности открытия :(
Проблема в том, что число выгружается в формате через запятую :(
а нужно через точку.

ЗЫ или это зависит от региональных установок? вроде они у меня штатные как для Офиса, так и для 1С
50. Артур Аюханов (artbear) 27.09.10 14:38
(49) + Исправление
В методе ЗаписатьДанныеЛиста(хмл)

нужно поправить код
	Попытка
		А = Число(ЗначЯчейки);
		ЭтоЧисло = Истина;
	Исключение
...Показать Скрыть
на код
	Попытка
		А = Число(ЗначЯчейки);
		ЭтоЧисло = Истина;
		ЗначЯчейки = СтрЗаменить(Формат(А, "ЧРД=."), Символы.НПП, ""); // Артур
	Исключение
...Показать Скрыть

ЗЫ кстати, приведенный код решает проблему неверного сохранения чисел более 999, при сохранении в строку в которых появляется неразрывный пробел.
При открытии подобного файла в Офис 2007 также будет ошибка открытия :(
51. Артур Аюханов (artbear) 30.09.10 07:50
Проблема из (30) по записи файла с количеством строк более 999 также не решена :(
для ее исправления нужно исправить код модуля
1. завести новую функцию
Функция ЧислоВСтроку(значениеЧисла) // Артур для исключения ошибок открытия файлов
Возврат СокрЛП(Формат(значениеЧисла, "ЧРД=.; ЧГ="));
КонецФункции
2. прописать ее использование
а) хмл.ЗаписатьАтрибут("spans", "1:" + ЧислоВСтроку(ЧислоСтрок)); // вместо хмл.ЗаписатьАтрибут("spans", "1:" + ЧислоСтрок);
б) хмл.ЗаписатьАтрибут("count", ЧислоВСтроку(Строки.Количество())); // Артур вместо //Строка(Строки.Количество())
хмл.ЗаписатьАтрибут("uniqueCount", ЧислоВСтроку(Строки.Количество())); // Артур вместо //Строка(Строки.Количество())

Прикрепил готовый файл для 8.1 с моими правками + дополнения от webstep
Прикрепленные файлы:
Excel2007_v81.epf
52. Роман Лиль (Lalei2008) 28.10.10 17:16
54. Юрий Португалов (Sprite) 04.02.12 16:25
Загружаю демо-конфигурацию 7.7

Получаю сообщение:
Папка=Шел.namespace(Архив+"\"+Путь);
{Глобальный модуль(365)}: Плохой тип переменной

Help me!!!
55. Юрий Зайцев (Yury1001) 07.02.12 17:32
Рановато плюсанул пример 7.7 нерабочий: плохой тип переменной стр. 363

Папка=Шел.namespace(Архив+"\"+Путь);

Архив = "D:\DataBase\Джигель\ЧтениеЗаписьExcel\Excel2007\Template.zip"
Путь = "D:\DataBase\Джигель\ЧтениеЗаписьExcel\Excel2007\Template.zip\_rels"
Архив+"\"+Путь = "D:\DataBase\Джигель\ЧтениеЗаписьExcel\Excel2007\Template.zip\D:\DataBase\Джигель\ЧтениеЗаписьExcel\Excel2007\Template.zip\_rels"

поправил, теперь плохой тип 404

ПутьФайла = "D:\DataBase\Джигель\ЧтениеЗаписьExcel\Excel2007\Template.zip\[Content_Types].xml"

чё к чему не пойму.
56. Юрий Зайцев (Yury1001) 07.02.12 17:34
(0) Вопросик в догонку: нужно выгрузить большой объем данных в excel 90 000 строк и штук 10 колонок, этим методом получится?
57. amatisol amatisol (amatisol) 25.03.12 22:43
Народ а че реально работает? А то сидят многие на openoffice и хотят чтоб у них ексели открывались нормально, если реально работает то плюсау и скачаю
58. Andrey Dyak (electronik) 07.05.12 14:00
В принципе, хорошая вешь нужная! С екзелем работаем если не все то через одного, поетому актуальность даного потрясающая. На основании даной разработки создал свою и что самое интерсное работает. Автору респект и уважение ну и заслуженое 5+++++
59. lesorubka (lesorubka) 23.07.12 11:58
Спасибо автору! Отлично работает! Жаль ушел от нас, столько бы еще сделал.
Царствие ему Небесное!!!
Istur; rybamech; +2 Ответить
60. Алекс Ю (AlexO) 10.10.12 18:00
(57) amatisol,
это создание текстовых XML-ек и упаковка их в zip.
Более ранние версии файлов Excel так создать не удастся.
61. Npoen Dzogchen (Dansur) 18.10.12 10:58
Ему еще много лет будут говорить спасибо. жаль что он это уже не услышит. Покойся с миром.
62. nnurik (nnurik) 08.02.13 11:00
Спасибо автору! Очень пригодилось.
63. Максим Евсенкин (tehas) 13.02.13 12:47
{ВнешняяОбработка.Excel2007.МодульОбъекта(119)}: Поле объекта не обнаружено (K)
НоваяСтрока[МассивБукв[ИндексСтроки]] = ЗначениеЯчейки;

файл (прайс 1С пересохранен в xlsx)
Прикрепленные файлы:
PRICE_1C.xlsx
64. Иван (Spartan) 29.03.13 10:51
(26),(48) Как-то так видимо:
Функция ПрочитатьСписокСтрок(ФайлСтрок)
	Строки = Новый СписокЗначений;
	
	хмл = Новый ЧтениеXML;
	хмл.ОткрытьФайл(ФайлСтрок);
	
	Пока хмл.Прочитать() Цикл
		//Если хмл.ТипУзла = ТипУзлаXML.Текст Тогда  // некорректно работает для пустых строк!!!
		//	Строки.Добавить(хмл.Значение);
		//КонецЕсли;
		// Spartan - 29.03.2013 - начало
		Если хмл.Имя = "t" И хмл.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			Если хмл.Прочитать() И хмл.Имя = "#text" Тогда
				Строки.Добавить(хмл.Значение);
			Иначе
				Строки.Добавить("");
			КонецЕсли; 
		КонецЕсли;
		// Spartan - 29.03.2013 - конец
	КонецЦикла;
	
	хмл.Закрыть();
	
	Возврат Строки;
КонецФункции
...Показать Скрыть
65. mozz mozz (mozz) 30.04.13 13:22
(64) Туда же:
(уже встроены багфиксы из (51) )
Процедура ЗаписатьДанныеЛиста(хмл)
	ЧислоСтрок = Лист.Количество();
	ЧислоКолонок = Лист.Колонки.Количество();
	
	Для иСтр = 0 По ЧислоСтрок - 1 Цикл
		хмл.ЗаписатьНачалоЭлемента("row");
		хмл.ЗаписатьАтрибут("r", ПолучитьИмяСтроки(иСтр));
		хмл.ЗаписатьАтрибут("spans", "1:" + ЧислоВСтроку(ЧислоСтрок)); // вместо хмл.ЗаписатьАтрибут("spans", "1:" + ЧислоСтрок); 
		
		Для иКол = 0 По ЧислоКолонок - 1 Цикл
			хмл.ЗаписатьНачалоЭлемента("c");
			хмл.ЗаписатьАтрибут("r", ПолучитьОбласть(иСтр, иКол));
			
			ЗначЯчейки = Лист.Получить(иСтр).Получить(иКол);
			Попытка
				А = Число(ЗначЯчейки);
				ЭтоЧисло = Истина;
				ЗначЯчейки = СтрЗаменить(Формат(А, "ЧРД=."), Символы.НПП, ""); // Артур
			Исключение
				ЭтоЧисло = Ложь;
			КонецПопытки;
			
			Т = ТипЗнч(ЗначЯчейки);
			Если НЕ ЭтоЧисло И ТипЗнч(ЗначЯчейки) = Тип("Строка") Тогда
				Если НЕ ЗначЯчейки = "" тогда // mozz 30.04.2013 (здесь вываливалось на пустых ячейках)
					хмл.ЗаписатьАтрибут("t", "s");
					Элем = СписокСтрок.НайтиПоЗначению(ЗначЯчейки);
					ЗначЯчейки = СписокСтрок.Индекс(Элем);
				КонецЕсли; // mozz 30.04.2013
			КонецЕсли;
			
			хмл.ЗаписатьНачалоЭлемента("v");
			хмл.ЗаписатьТекст(Строка(ЗначЯчейки));
			хмл.ЗаписатьКонецЭлемента();
			
			хмл.ЗаписатьКонецЭлемента();
		КонецЦикла;
		
		хмл.ЗаписатьКонецЭлемента();
	КонецЦикла;
КонецПроцедуры
...Показать Скрыть
66. mozz mozz (mozz) 07.05.13 13:44
(63) tehas,

в функции:
Функция ОткрытьЛист(НомерЛиста) Экспорт
найди:
НоваяСтрока[МассивБукв[ИндексСтроки]] = ЗначениеЯчейки;


замени на:

Если Лист.Колонки.Найти(МассивБукв[ИндексСтроки]) = Неопределено тогда
				Лист.Колонки.Добавить(МассивБукв[ИндексСтроки]);
			КонецЕсли;
			  
			НоваяСтрока[МассивБукв[ИндексСтроки]] = ЗначениеЯчейки;
...Показать Скрыть


и все взлетит!
67. 1cSupport - третий (Зеленоград) 04.09.13 11:35
Спасибо, Мастер! Покойся с миром!
68. 1cSupport - третий (Зеленоград) 05.09.13 13:27
Спасибо, Мастер! Покойся с миром!



Коллеги, сайт автора перестал открываться. Там, как минимум, были полезные разработки.

Есть ли необходимость и возможность сохранения ценных ресурсов в подобных случаях, кроме archive.org?
Отвечайте или здесь, или в личку. Если это важно многим - будем думать, как реализовать.
69. Макас (makas) 27.09.13 12:34
ОткрытьФайлЭкзекль2007


может быть ОткрытьФайлЭкзель2007 ?
70. Александр Лобачёв (SANILLA) 05.10.13 03:36
да ну на фик, не уже ли, так и есть, щас попробую, если работает, то точно то что надо. Благодарю!
71. Александр Лобачёв (Myskyl) 05.10.13 03:39
да да то что и искал, как раз нужен был пример работы с Экселем, а тут и ещё без всяких врешних компонент, супер, спасибо
72. Илья Курганников (host_kms) 10.10.13 08:55
Папка=Шел.namespace(Архив+"\"+Путь);
{Глобальный модуль(365)}: Плохой тип переменной

Кто-нибудь решил эту проблему?
73. mukoza (mukoza) 12.12.13 10:18
Поддерживаю предыдущий вопрос. Неужели у ни у кого не возникает подобной ошибки?
74. Григорий Усольцев (ugn-omsk) 15.03.15 18:17
Папка=Шел.namespace(Архив+"\"+Путь);
{Глобальный модуль(365)}: Плохой тип переменной

Ошибка возникает на Windows7, в XP все работает "из коробки".
На 7-ке видимо по-другому работает namespace в javascript.
Вобщем, глубоко не ковырял, ибо нет времени.
Обошел проблему очень тупо, ибо не программист.
Просто "подрезал" местами длинные пути до их нужного значения.
Например, переменная Архив принимает значение X:\Путь_к_БД\Template.zip
а переменная Путь должна принять значение xl\workbook.xml (и не только его, а всю структуру внутри архива). Но в Win7 переменная Путь принимает значение X:\Путь_к_БД\Template.zip\xl\workbook.xml
На выходе получаем Архив+"\"+Путь = X:\Путь_к_БД\Template.zip\X:\Путь_к_БД\Template.zip\xl\workbook.xml
Конечно, это будет "плохой тип переменной" )))

Вот рабочий вариант - просто замените текст функции в глобальном модуле.

//*******************************************
Функция архив_ПросмотрРекурс(Архив,Путь="",Сп)
// Функция просматривает содержимое файла Template.zip
// по всем вложенным папкам,
// и заполняет список путями ко всем файлам и папкам



// Исправляем некорректную работу с путями в Windows7
Если Путь <> "" Тогда
Путь=СтрЗаменить(Путь, Архив,""); // Убираем в переменной путь то, что уже записано в переменной Архив (дублирование)
Если Сред(Путь,1,1)="\" Тогда
Путь=Сред(Путь,2); // Если первым символом в пути является разделитель \, то его тоже уберем
КонецЕсли;
КонецЕсли;


Скрипт=СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.language="javascript";
Шел=СоздатьОбъект("shell.application");

//Сообщить(Архив+""+Путь);
//Сообщить("Архив: "+Архив);
//Сообщить("Путь: "+Путь);
//Сообщить("-----------------------------------------");




Папка=Шел.namespace(Архив+""+Путь);
Скрипт.AddObject("Папка",Папка);
Вложения=Скрипт.Eval("new Enumerator(Папка.Items())");
Пока Вложения.atEnd(0)=0 Цикл

// Таже беда под Win 7. Будем "резать" длиные пути, используя промежуточную переменную //ПутьДляДобавления
ПутьДляДобавления=СтрЗаменить(Вложения.item(0).path,Архив,"");
Если Сред(ПутьДляДобавления,1,1)="\" Тогда
ПутьДляДобавления=Сред(ПутьДляДобавления,2);
КонецЕсли;
//Сп.ДобавитьЗначение(Вложения.item(0).path);
Сп.ДобавитьЗначение(ПутьДляДобавления);

//Сообщить("Добавлено в список: "+ Строка(Вложения.item(0).path));
Если Вложения.item(0).IsFolder=-1 Тогда
архив_ПросмотрРекурс(Архив,Вложения.item(0).path,Сп);
КонецЕсли;
Вложения.moveNext(0);
КонецЦикла;
КонецФункции
//*******************************************
...Показать Скрыть


Если, кто из программистов, сделает решение этой проблемы элегантнее - большой респект ему!
А пока вот так, коряво, зато работает!
Надеюсь, кому-то поможет.
75. Григорий Усольцев (ugn-omsk) 15.03.15 18:31
(55) Yury1001,
Вы пошли тем же путем, что и я.

поправил, теперь плохой тип 404

ПутьФайла = "D:\DataBase\Джигель\ЧтениеЗаписьExcel\Excel2007\Template.zip\[Content_Types].xml"


Здесь нужно добиться, чтобы
ПутьФайла = "D:\DataBase\Джигель\ЧтениеЗаписьExcel\Excel2007\Template.zip\[Content_Types].xml",
т.е. просто [Content_Types].xml
Постом выше привел код. Понимаю, что уже давно неактуально, но если вдруг на будущее кому-то пригодится.
Потому как идея действительно очень интересная!
76. Дмитрий Самончик (Пикачу) 28.04.15 17:38
7.7 такое не понимает:

Пока Вложения.atEnd<a rel="noindex,nofollow"...

Это код для 8?
А можно для 7.7?
77. sai_ NT (sai_NT) 19.01.16 17:57
(76) Пикачу, Там скопированы стили с кодом html, правильно так:
Пока Вложения.atEnd(0)=0 Цикл
...


и так далее, то есть смело удаляй тег а, оставив только текст: <a hrеf=...>бла-бла</a> -> бла-бла