Страницы: 1
RSS
VBA. Получить изображение как blob / Сохранить изображение
 
Всем привет.

На листе эксель присутствует изображение. Требуется получить его (изображение/данные о нем) в бинарном виде.

1. Возможно ли это сделать без сохранения? (код)
2. Если сохранять, то как? (код)


Спасибо.
Изменено: nerv - 14.03.2013 00:43:13
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Саш, привет! У Игоря на сайте посмотри - по сохранению у него там было.
 
Сохранить изображение с листа в файл несложно:
http://excelvba.ru/code/ExportPictures
(«стандартный» способ, через диаграмму)


Впрочем, можно и без сохранения попробовать, с помощью WinAPI: (вот только зачем)
http://programmersforum.ru/showthread.php?t=54492
(в надстройке в той теме был подобный код)
Этот способ не работает при application.ScreenUpdating=False


Насчёт BLOB - тут я не специалист, но примеры есть в гугле по запросу «vb6 blob»
(просто создается байтовый массив путем чтения файла с диска)



PS: Ищу способ сохранить картинку с листа в файл, БЕЗ использования диаграмм,
и кучи кода WinAPI. Формат сохранения: JPG или PNG/ Должно работать в Excel 2003...2013

Есть у кого идеи, как сделать это просто и быстро?
Нужен быстрый стабильно работающий код, желательно без Copy и Paste


PPS: Ещё ищу способ сжатия картинки в файле JPG (пропорциональное уменьшение размеров, с потерей качества), без импорта/экспорта картинки на лист Excel
Может, кто подскажет, как сделать это средствами WinAPI, без использования сторонних библиотек и программ?
 
Юрий, Игорь, спасибо!  :)

Я почему-то наивно полагал, что есть способ проще, без диаграмм. Но, коли нет, и этим буду доволен )

Цитата
EducatedFool пишет:
(просто создается байтовый массив путем чтения файла с диска)
ну да. Наивно полагал, что можно получить сведения об изображении без записи его на диск.

По вопросу экспорта изображений нагугливаются либо диаграммы (copy-paste), либо Win API.
http://xlvba.fr.yuku.com/topic/207
http://www.andypope.info/vba/gex.htm
http://www.jpsoftwaretech.com/export-excel-range-to-a-picture-file/
http://www.mrexcel.com/forum/excel-questions/233108-visual-basic-applications-code-export-image-file-preferably-jpg.html
http://www.jpsoftwaretech.com/export-excel-range-to-a-picture-file-redux/#content

На самом деле экспортировать картинки мне нужно из Word :)
В поисках решения пришел к эксель. Это, конечно, через одно место, но...

Цитата
EducatedFool пишет:
PS: Ищу способ сохранить картинку с листа в файл, БЕЗ использования диаграмм,
и кучи кода WinAPI. Формат сохранения: JPG или PNG/ Должно работать в Excel 2003...2013

Есть у кого идеи, как сделать это просто и быстро?
Нужен быстрый стабильно работающий код, желательно без Copy и Paste
Идея есть. Вчера нагуглил ее когда искал. Гуглил долго. Думал гугл сломаю )
Идея проста как два пальца - сохранить файл как html.
Наверно, на ней и остановлюсь.

Цитата
EducatedFool пишет:
PPS: Ещё ищу способ сжатия картинки в файле JPG (пропорциональное уменьшение размеров, с потерей качества), без импорта/экспорта картинки на лист Excel
Не знаю насколько правильное направление, но есть такие функции у класса StdFunctions, как
LoadPicture
и
SavePicture
У первой в опциях задаются размеры.

Еще ссылка по теме
http://office.microsoft.com/en-us/word-help/save-a-picture-as-a-jpg-gif-or-png-HA010354818.aspx
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Цитата
Идея проста как два пальца - сохранить файл как html.
Это я знаю. Но - не подходит.
А как потом разобрать, где какая картинка?

К примеру, у меня есть столбец с картинками, а справа от них - столбец с имена для файлов.
Каждую картинку надо сохранить под заданным именем.
А при сохранении в HTML имеем кучу картинок, и фиг угадаешь, из какой ячейки взята та или иная картинка...


Способ с диаграммами мне не нравится.
Может, я что-то делаю не так, но мне не удалось написать код,
который бы корректно сохранял картинку в Excel 2003, 2007 и 2010
(в 2007-м диаграммы стали с закруглёнными углами - поэтому картинка вставляется не с верхнего левого угла, а с небольшим сдвигом, причем этот сдвиг зависит от версии Excel)
У диаграммы есть свойство для отключения скруглённых углов, но что-то оно мне не помогло
(картинки так и выгружаются с 2 белыми полосками слева и сверху)

Может, у кого есть код (сохранение картинки через диаграмму), нормально работающий в любой версии Excel?
(я пробовал код с сайта Димы - не получилось его сделать универсальным)


Цитата
Не знаю насколько правильное направление, но есть такие функции у класса StdFunctions, как
Направление правильное, но получить объект типа IPictureDisp из картинки на листе - это такой гемор...
надо много WinAPI использовать (да и, скорее всего, не будет работать при отключеннном ScreenUpdating)
Если кто знает (и пробовал применять) способ преобразования картинки с листа в IPictureDisp - пожалуйста, поделитесь примером.
(я уже и на WinAPI согласен, лишь бы стабильно работало)
Изменено: EducatedFool - 14.03.2013 22:42:31
 
Цитата
EducatedFool пишет:
Это я знаю. Но - не подходит.
А как потом разобрать, где какая картинка?
Сохраняет в том порядке, в кот. перебирает в цикле. Последняя картинка - снимок листа. По крайней мере у меня так.

Пример > 100 kb
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Не хотелось бы использовать такой способ, поскольку нет гарантий,
что на самом деле такой порядок картинок в выгрузке.

Например, один раз при экспорте добавилась «лишняя» первая картинка:
http://ExcelVBA.ru/pictures/20130315-wd8-33kb.jpg
(похоже, картинка из активной ячейки выгружается первой, дополнительно к остальным картинкам)

Кроме того, если есть картинки в примечании - выгружаются и они тоже,
после чего определить порядок вообще сложно.

Да и хотелось бы делать это в цикле, чтобы можно было только некоторые картинки экспортировать.

Подумываю изначально вставлять на лист картинки в виде элементов управления Image,
чтобы потом было легко выгрузить из обратно в файлы


PS: Подождём визита в эту тему Владимира (ZVI) - у него на любой вопрос по VBA Excel есть готовое решение, о существовании которого большинство форумчан даже не догадывалось ранее)
Изменено: EducatedFool - 15.03.2013 00:33:54
 
Цитата
EducatedFool пишет:
Не хотелось бы использовать такой способ, поскольку нет гарантий,
что на самом деле такой порядок картинок в выгрузке.
Согласен, что он не надежный, но, глядя на то, как обстоят дела с экспортом изображений, особо вариантов нет.
1. лес Win API
2. чудо диаграммы
3. придумай сам (html etc.)

Насчет выгрузки в html. Насколько я понял, изображения с Visible = False не выгружаются в 2010.

Без копи-паста не обойдется, но тем не менее мысли в слух: создать новый чистый лист, скопировать на него картинку, сохранить лист как html.

Цитата
EducatedFool пишет:
Подумываю изначально вставлять на лист картинки в виде элементов управления Image,
чтобы потом было легко выгрузить из обратно в файлы
не всегда есть такая возможность
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Как оказалось, сохранить изображение из документа Word в файл достаточно просто

Код
Sub io()
    Dim Number As Long
    Dim Bytes() As Byte
    
    Number = FreeFile()
    Bytes = ThisDocument.InlineShapes(1).Range.EnhMetaFileBits
    
    Open "C:\pic.bmp" For Binary Access Write As Number
        Put Number, , Bytes
    Close Number
    
    MsgBox "Done", vbInformation
End Sub


Нюансы: если попытаться открыть (просмотреть) изображение через любой просмотрщик или программу, оно не откроется, но, если импортировать его в ворд, будет отображаться корректно. В деталях пока не разбирался.
Изменено: nerv - 21.03.2013 17:49:11
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
А я всё же через WinAPI решил все делать:
http://excelvba.ru/code/ResizeImages
(картинки с листа сохраняются функцией GdipSaveImageToFile, через буфер обмена)
 
угу, спасибо. Еще одно спасибо (заочное) товарищу Скрипту с программерс, за хорошую идею.

Пример без WinAPI

Код
Sub Example()
    Dim Img As ImageFile
    Dim IP As ImageProcess

    Set Img = CreateObject("WIA.ImageFile")
    Set IP = CreateObject("WIA.ImageProcess")
    
    Img.LoadFile "C:\ava_0043.bmp"
    
    IP.Filters.Add IP.FilterInfos("Convert").FilterID
    IP.Filters(1).Properties("FormatID").Value = wiaFormatJPEG
    IP.Filters(1).Properties("Quality").Value = 5
    
    Set x = IP.Apply(Img)
    
    Img.SaveFile "C:\pic1.jpg"
End Sub


Используется Windows Image Acquisition (WIA).

Больше примеров и инфы:
http://msdn.microsoft.com/ru-RU/library/windows/desktop/ms630819(v=vs.85).aspx
http://stackoverflow.com/questions/2313395/wia-document-handling-status-returns-0-even-though-the-adf-has-pages-loaded


Насколько я понял, куча параметров и настроек, т.е. гибко.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Саш, если я не ошибаюсь, данную библиотеку освоил anvg (ссылка на источник) и уже потом поделился с остальными.
А вот ссылочка на dll'ку, возможно кому-то понадобиться, т.к. для обработки изображений необходима WIA v2 (пришлось устанавливать, так как у меня изначально была только v1.01)
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
LightZ, спасибо, Богдан. Я не натыкался на ту ссылку, сразу на инглише гуглил ) Насколько понял, нормальная либа. Поддержка с Windows ME+.

Единственная проблема - сохранить файл на диск из книги/документа.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Всё же, если необходимо использовать изображение исходного размера (копирование в буфер даёт изображение, которое имеет, как правило, меньшую ширину/высоту в пикселах), то, по-моему мнению, лучше использовать сохранение страницы в файл html. Чтобы однозначно определить нужное изображение необходимо будет задать ему своё имя (допустим mypic1), тогда в коде html файла его можно будет найти по строке
<v:shape id="mypic1"
и поиском следующей строки
<v:imagedata src="Страница.files/Книга1_25305_image001.jpg"
найти относительный путь и имя файла-растра.
В случае сохранения только одно листа 2003 и 2010 ведут себя одинаково (рисунки сохраняются в отдельную папку ИмяФайла.files
Изменено: anvg - 22.03.2013 05:35:18
 
Попробуй ADODB.Stream
There is no knowledge that is not power
 
anvg, спасибо за ответ!
Цитата
anvg пишет:
Чтобы однозначно определить нужное изображение необходимо будет задать ему своё имя (допустим mypic1
я это делал в данной теме несколькими постами выше, но смекалки не хватило на
Цитата
anvg пишет:
тогда в коде html файла его можно будет найти по строке
<v:shape id="mypic1"
и поиском следующей строки
<v:imagedata src=" Страница.files/Книга1_25305_image001.jpg"
найти относительный путь и имя файла-растра.
:)

Johny, можно пример?
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Вчера написал тестовую программу на VB.NET.
Она показывает список всех изображений и позволяет сохранять изображения, при этом Excel не требуется вообще.
Есть ещё один вариант - написать DLL на VB.NET и вызвать класс из VBA, но что-то у меня вчера не получилось. Видать, проблемы с регистрацией DLL. VBA пишет "Can't create ActiveX object".
Времени разбираться не было, поэтому пока только экзешник.
Если разберусь, то можно оформить в виде DLL и привязать к VBA. )
Вот такие перспективы.  :D
Если такой вариант подойдёт, то притащу экзешник (требуется .NET Framework 4.5).
There is no knowledge that is not power
 
Цитата
(требуется .NET Framework 4.5)
А на 3.5 уже никак?
 
Цитата
anvg пишет:
А на 3.5 уже никак?
Нет, так как в .NET 4.5 добавлен родной zip-архиватор (класс ZipArchive и ZipArchiveEntry).
There is no knowledge that is not power
Страницы: 1
Читают тему
Наверх