Vba сохранить картинки excel

VBA Code Save AS Picture File Macro

Excel Save As Picture

Not As Easy As You’d Think…

One would think that saving something as a picture file (png, jpg, etc…) inside Excel with VBA would be a pretty straightforward exercise. Unfortunately, the “Save as Picture” functionality only exists for saving images of Charts (called exporting). This leaves saving pictures of shapes, icons, and cell ranges void of any VBA automation.

However, with a little bit of creativity, we can utilize the chart object to store our desired image and use the chart object’s Export function to create the image file that we can manually generate by right-clicking and selecting Save as Picture…

In this article I’ll walk you through the basic concept of what the VBA code is doing and also go through two VBA macro examples pertaining to saving shapes/icons and cell ranges in various file formats.

Methodology

Not many people know this but Charts can actually store shapes/objects inside of them. For example, if you have ever copied a textbox and pasted it while a chart is selected, you’ll notice the textbox object appears to be grouped with the chart. Meaning, if you move the chart to a different location, the textbox would move right along with it. What is actually occurring is the textbox is getting embedded within the chart and is essentially now a component of the chart object (think legend, chart title, chart series, axis, etc…).

Notice that the chart object is selected while selecting the textbox? This indicates the textbox has been embedded into the chart object.

Notice that the chart object is selected while selecting the textbox? This indicates the textbox has been embedded into the chart object.

The fact that charts in Excel can absorb other objects is what we will be utilizing to workaround the fact that shapes and other objects cannot be saved as a picture in VBA.

Before we dive into the VBA code, the concept the macro will be utilizing will be to isolate the object you want to save as a picture file and also generating a blank/empty chart object.

VBA Code To Save As Image File

With those two objects in place, the VBA code will simply paste the desired object into the Chart Object (kind of like converting it into a chart!).

VBA Code To Save As Image File

With this concept in mind, let’s take a look at the VBA code I’ve proposed to get this job done!

Save Shape As A PNG File [VBA Code]

Hopefully the following VBA macro is easily to follow along, but I’ll outline essentially the steps it is doing so you can customize it accordingly if needed.

  1. Determine if a shape is selected, if not, don’t proceed. Store the selected shape to a variable (ActiveShape)

  2. Generate a Chart Object that is the exact same size as the selected shape

  3. Remove the chart’s Fill and Border to make the background transparent

  4. Copy the selected shape and Paste it into the Chart Object

  5. Export the Chart Object as a PNG file and save to the user’s desktop

  6. Delete the chart so it appears like nothing has occurred to the user

Sub SaveShapeAsPicture()
‘PURPOSE: Save a selected shape/icon as a PNG file to computer’s desktop
‘SOURCE: www.thespreadsheetguru.com

Dim cht As ChartObject
Dim ActiveShape As Shape
Dim UserSelection As Variant

‘Ensure a Shape is selected
  On Error GoTo NoShapeSelected
    Set UserSelection = ActiveWindow.Selection
    Set ActiveShape = ActiveSheet.Shapes(UserSelection.Name)
  On Error GoTo 0

‘Create a temporary chart object (same size as shape)
  Set cht = ActiveSheet.ChartObjects.Add( _
    Left:=ActiveCell.Left, _
    Width:=ActiveShape.Width, _
    Top:=ActiveCell.Top, _
    Height:=ActiveShape.Height)

‘Format temporary chart to have a transparent background
  cht.ShapeRange.Fill.Visible = msoFalse
  cht.ShapeRange.Line.Visible = msoFalse

    ‘Copy/Paste Shape inside temporary chart
  ActiveShape.Copy
  cht.Activate
  ActiveChart.Paste

   ‘Save chart to User’s Desktop as PNG File
  cht.Chart.Export Environ(«USERPROFILE») & «Desktop» & ActiveShape.Name & «.png»

‘Delete temporary Chart
  cht.Delete

‘Re-Select Shape (appears like nothing happened!)
  ActiveShape.Select

Exit Sub

‘ERROR HANDLERS
NoShapeSelected:
  MsgBox «You do not have a single shape selected!»
  Exit Sub

End Sub

Save Range As A JPG File [VBA Code]

Hopefully the following VBA macro is easily to follow along, but I’ll outline essentially the steps it is doing so you can customize it accordingly if needed.

  1. Determine if a cell range is selected, if not, don’t proceed.

  2. Copy/Paste the range as a picture and store the picture to a variable (ActiveShape)

  3. Generate a Chart Object that is the exact same size as the selected shape

  4. Remove the chart’s Fill and Border to make the background transparent

  5. Copy the selected shape and Paste it into the Chart Object

  6. Export the Chart Object as a PNG file and save to the user’s desktop

  7. Delete the generated chart & picture so it appears like nothing has occurred to the user

Sub SaveRangeAsPicture()
‘PURPOSE: Save a selected cell range as a JPG file to computer’s desktop
‘SOURCE: www.thespreadsheetguru.com

Dim cht As ChartObject
Dim ActiveShape As Shape

‘Confirm if a Cell Range is currently selected
  If TypeName(Selection) <> «Range» Then
    MsgBox «You do not have a single shape selected!»
    Exit Sub
  End If

‘Copy/Paste Cell Range as a Picture
  Selection.Copy
  ActiveSheet.Pictures.Paste(link:=False).Select
  Set ActiveShape = ActiveSheet.Shapes(ActiveWindow.Selection.Name)

  ‘Create a temporary chart object (same size as shape)
  Set cht = ActiveSheet.ChartObjects.Add( _
    Left:=ActiveCell.Left, _
    Width:=ActiveShape.Width, _
    Top:=ActiveCell.Top, _
    Height:=ActiveShape.Height)

‘Format temporary chart to have a transparent background
  cht.ShapeRange.Fill.Visible = msoFalse
  cht.ShapeRange.Line.Visible = msoFalse

    ‘Copy/Paste Shape inside temporary chart
  ActiveShape.Copy
  cht.Activate
  ActiveChart.Paste

   ‘Save chart to User’s Desktop as PNG File
  cht.Chart.Export Environ(«USERPROFILE») & «Desktop» & ActiveShape.Name & «.jpg»

‘Delete temporary Chart
  cht.Delete
  ActiveShape.Delete

‘Re-Select Shape (appears like nothing happened!)
  ActiveShape.Select

End Sub

I Hope This Helped!

Hopefully, I was able to explain how you can use VBA to create image files in Excel. If you have any questions about this technique or suggestions on how to improve it, please let me know in the comments section below.

Chris Newman 2020 - TheSpreadsheetGuru

About The Author

Hey there! I’m Chris and I run TheSpreadsheetGuru website in my spare time. By day, I’m actually a finance professional who relies on Microsoft Excel quite heavily in the corporate world. I love taking the things I learn in the “real world” and sharing them with everyone here on this site so that you too can become a spreadsheet guru at your company.

Through my years in the corporate world, I’ve been able to pick up on opportunities to make working with Excel better and have built a variety of Excel add-ins, from inserting tickmark symbols to automating copy/pasting from Excel to PowerPoint. If you’d like to keep up to date with the latest Excel news and directly get emailed the most meaningful Excel tips I’ve learned over the years, you can sign up for my free newsletters. I hope I was able to provide you some value today and hope to see you back here soon! — Chris

Хитрости »

1 Май 2011              182174 просмотров


Получили по почте файл-прайс с изображениями товара и эти картинки нужны в отдельной папки, а не на листе? Например для загрузки на сайт. Или для других целей. Подобной команды в Excel нет. Вставить картинки можно, а вот обратно к сожалению никак. Хорошо, если картинок штук 10, а если 100? А если таких книг много? И из всех надо сохранить картинки? Решил поделиться кодами, которые могут сохранять картинки из листа Excel в папку.
Если не знаете как применять коды Visual Basic for Applications, то настоятельно рекомендую к прочтению эти статьи:
Что такое макрос и где его искать?
Что такое модуль? Какие бывают модули?
Если хотите использовать один из нижеприведенных кодов, то следует создать стандартный модуль, скопировать нужные код и вставить его в этот модуль.

  • Сохранение выделенной картинки в файл
  • Сохранение всех картинок из всех выбранных файлов Excel в папку
  • Сохранить выделенный диапазон в картинку
  • Сохраняем все картинки с листа в папку с записью в ячейки имен картинок
  • Сохранить картинки с листа с именами картинок из ячеек
Сохранение выделенной картинки в файл

Все, что потребуется это выделить объект/картинку и выполнить нижеприведенный код:

Sub Save_Sel_Object_As_Picture()
    Dim sName As String, oObj As Object, wsTmpSh As Worksheet
    If VarType(Selection) <> vbObject Then
        MsgBox "Выделенная область не является объектом!", vbCritical, "www.excel-vba.ru"
    Exit Sub
    End If
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Set oObj = Selection: oObj.Copy
    Set wsTmpSh = ThisWorkbook.Sheets.Add
    sName = ActiveWorkbook.FullName & "_" & ActiveSheet.Name & "_" & oObj.Name
    With wsTmpSh.ChartObjects.Add(0, 0, oObj.Width, oObj.Height).Chart
        .ChartArea.Border.LineStyle = 0
        .Parent.Select
        .Paste
        .Export Filename:=sName & ".gif", FilterName:="GIF"
        .Parent.Delete
    End With
    wsTmpSh.Delete
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub

Если необходимо сохранить не только картинки, но и другие объекты, то необходимо в коде в строке: If oObj.Type = 13 Then изменить цифру. В коде комментариями указано, какая цифра какой тип обозначает. Так же можно изменить и расширение итогового файла с «.gif» на «.jpg». Достаточно найти расширение gif в коде(в двух местах) и заменить их на jpg. Если ни один объект не выделен, то ничего не произойдет.


Сохранение всех картинок из всех выбранных файлов Excel в папку

Sub Save_Object_As_Picture()
    Dim avFiles, li As Long, oObj As Object, wsSh As Worksheet, wsTmpSh As Worksheet
    Dim sImagesPath As String, sBookName As String, sName As String
    Dim wbAct As Workbook
    Dim IsForEachWbFolder As Boolean
 
    avFiles = Application.GetOpenFilename("Excel Files(*.xls*),*.xls*", , "Выбрать файлы", , True)
    If VarType(avFiles) = vbBoolean Then Exit Sub
 
    IsForEachWbFolder = (MsgBox("Сохранять картинки каждой книги в отдельную папку?", vbQuestion + vbYesNo, "www.excel-vba.ru") = vbYes)
 
    If Not IsForEachWbFolder Then
        sImagesPath = Environ("userprofile") & "desktopimages" '"
        If Dir(sImagesPath, 16) = "" Then
            MkDir sImagesPath
        End If
    End If
    On Error Resume Next
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Set wsTmpSh = ThisWorkbook.Sheets.Add
    For li = LBound(avFiles) To UBound(avFiles)
        Set wbAct = Workbooks.Open(avFiles(li), False)
        'создаем папку для сохранения картинок
        If IsForEachWbFolder Then
            sImagesPath = wbAct.Path & "" & wbAct.Name & "_images"
            If Dir(sImagesPath, 16) = "" Then
                MkDir sImagesPath
            End If
        End If
        sBookName = wbAct.Name
        For Each wsSh In Sheets
            For Each oObj In wsSh.Shapes
                If oObj.Type = 13 Then
                    '13 - картинки
                    '1 - автофигуры
                    '3 - диаграммы
                    oObj.Copy
                    sName = ActiveWorkbook.Name & "_" & wsSh.Name & "_" & oObj.Name
                    With wsTmpSh.ChartObjects.Add(0, 0, oObj.Width, oObj.Height).Chart
                        .ChartArea.Border.LineStyle = 0
                        .Parent.Select
                        .Paste
                        .Export Filename:=sImagesPath & sName & ".jpg", FilterName:="JPG"
                        .Parent.Delete
                    End With
                End If
            Next oObj
        Next wsSh
        wbAct.Close 0
    Next li
    Set oObj = Nothing: Set wsSh = Nothing
    wsTmpSh.Delete
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    MsgBox "Объекты сохранены", vbInformation, "www.excel-vba.ru"
End Sub

Код позволяет выбрать одну или несколько книг Excel и сохраняет все картинки со всех листов выбранных книг. При запуске кода предлагается выбрать файлы Excel, картинки из которых надо сохранить. После этого появится запрос: «Сохранять картинки каждой книги в отдельную папку?»

  • Да — для каждой книги будет создана своя папка images, в которую будут сохранены картинки с именами вида: ИмяКниги_ИмяЛиста_ИмяФигуры
  • Нет — на рабочем столе пользователя будет создана папка images, в которую будут сохранены картинки с именами вида: ИмяКниги_ИмяЛиста_ИмяФигуры

Если необходимо сохранить не только картинки, но и другие объекты, то необходимо в коде в строке: If oObj.Type = 13 Then изменить цифру. В коде комментариями указано, какая цифра какой тип обозначает. Так же можно изменить и расширение итогового файла с «.jpg» на «.gif». Достаточно найти расширение jpg в коде(в двух местах) и заменить их на gif. В данном коде я намеренно сделал сохранение в формат jpg, чтобы можно было сравнить с предыдущим кодом и увидеть как правильно менять расширение(формат) файла.


Сохранить выделенный диапазон в картинку

Данные код сохраняет выделенный на листе диапазон в картинку.

Sub Range_to_Picture()
    Dim sName As String, wsTmpSh As Worksheet
    If TypeName(Selection) <> "Range" Then
        MsgBox "Выделенная область не является диапазоном!", vbCritical, "www.excel-vba.ru"
        Exit Sub
    End If
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    With Selection
        .CopyPicture
        Set wsTmpSh = ThisWorkbook.Sheets.Add
        sName = ActiveWorkbook.FullName & "_" & ActiveSheet.Name & "_Range"
        With wsTmpSh.ChartObjects.Add(0, 0, .Width, .Height).Chart
            .ChartArea.Border.LineStyle = 0
            .Parent.Select
            .Paste
            .Export Filename:=sName & ".gif", FilterName:="GIF"
            .Parent.Delete
        End With
    End With
    wsTmpSh.Delete
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub

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


СОХРАНЯЕМ ВСЕ КАРТИНКИ С ЛИСТА В ПАПКУ С ЗАПИСЬЮ В ЯЧЕЙКИ ИМЕН КАРТИНОК

Картинки на текст
Код ниже сохраняет все картинки на активном листе в папку

images

, которая создается в папке с книгой Excel, картинки из которой сохраняются. Если папки

images

нет — она будет создана. Картинкам даются имена

«img1», «img2», «img3»

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

Sub Save_Object_As_Picture()
    Dim li As Long, oObj As Shape, wsSh As Worksheet, wsTmpSh As Worksheet
    Dim sImagesPath As String, sName As String
 
    sImagesPath = ActiveWorkbook.Path & "images" '"
    If Dir(sImagesPath, 16) = "" Then
        MkDir sImagesPath
    End If
    On Error Resume Next
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Set wsSh = ActiveSheet
    Set wsTmpSh = ActiveWorkbook.Sheets.Add
    For Each oObj In wsSh.Shapes
        If oObj.Type = 13 Then
            li = li + 1
            oObj.Copy
            sName = "img" & li
            With wsTmpSh.ChartObjects.Add(0, 0, oObj.Width, oObj.Height).Chart
                .ChartArea.Border.LineStyle = 0
                .Parent.Select
                .Paste
                .Export Filename:=sImagesPath & sName & ".jpg", FilterName:="JPG"
                .Parent.Delete
            End With
            oObj.TopLeftCell.Value = sName
            oObj.Delete 'удаляем картинку с листа
        End If
    Next oObj
    Set oObj = Nothing: Set wsSh = Nothing
    wsTmpSh.Delete
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    MsgBox "Объекты сохранены в папке: " & sImagesPath, vbInformation, "www.excel-vba.ru"
End Sub

В коде все так же, как в кодах выше(можно сохранять другие объекты, можно изменить формат сохраняемых картинок). Только при этом в ячейку, в которой была картинка записывается имя, с которым эта картинка была сохранена в папку на компьютере. Сама картинка при этом удаляется. Если удалять не надо, то необходимо просто удалить строку:
oObj.Delete ‘удаляем картинку с листа
Если необходимо записать в ячейку не только имя картинки, но и полный путь(включая путь к папке и расширение картинки), то надо вместо строки:
oObj.TopLeftCell.Value = sName
записать такую:
oObj.TopLeftCell.Value = sImagesPath & sName & «.jpg»


Сохранить картинки с листа с именами картинок из ячеек

Пожалуй, самый популярный код. Он сохраняет картинки из активного листа с именами, взятыми из ячеек, в которых эти картинки расположены. При этом можно указать, чтобы имена брались из той же строки, но другого столбца:

Sub Save_Object_As_Picture_NamesFromCells()
    Dim li As Long, oObj As Shape, wsSh As Worksheet, wsTmpSh As Worksheet
    Dim sImagesPath As String, sName As String
    Dim lNamesCol As Long, s As String
 
    s = InputBox("Укажите номер столбца с именами для картинок" & vbNewLine & _
                 "(0 - столбец в котором сама картинка)", "www.excel-vba.ru", "")
    If StrPtr(s) = 0 Then Exit Sub
    lNamesCol = Val(s)
 
    sImagesPath = ActiveWorkbook.Path & "images" '"
    If Dir(sImagesPath, 16) = "" Then
        MkDir sImagesPath
    End If
'    On Error Resume Next
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Set wsSh = ActiveSheet
    Set wsTmpSh = ActiveWorkbook.Sheets.Add
    For Each oObj In wsSh.Shapes
        If oObj.Type = 13 Then
            oObj.Copy
            If lNamesCol = 0 Then
                sName = oObj.TopLeftCell.Value
            Else
                sName = wsSh.Cells(oObj.TopLeftCell.Row, lNamesCol).Value
            End If
            'если в ячейке были символы, запрещенные
            'для использования в качестве имен для файлов - удаляем
            sName = CheckName(sName)
            'если sName в результате пусто - даем имя unnamed_ с порядковым номером
            If sName = "" Then
                li = li + 1
                sName = "unnamed_" & li
            End If
            With wsTmpSh.ChartObjects.Add(0, 0, oObj.Width, oObj.Height).Chart
                .ChartArea.Border.LineStyle = 0
                .Parent.Select
                .Paste
                .Export Filename:=sImagesPath & sName & ".jpg", FilterName:="JPG"
                .Parent.Delete
            End With
        End If
    Next oObj
    Set oObj = Nothing: Set wsSh = Nothing
    wsTmpSh.Delete
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    MsgBox "Объекты сохранены в папке: " & sImagesPath, vbInformation, "www.excel-vba.ru"
End Sub
'---------------------------------------------------------------------------------------
' Procedure : CheckName
' Purpose   : Функция проверки правильности имени
'---------------------------------------------------------------------------------------
Function CheckName(sName As String)
    Dim objRegExp As Object
    Dim s As String
    Set objRegExp = CreateObject("VBScript.RegExp")
    objRegExp.Global = True: objRegExp.IgnoreCase = True
    objRegExp.Pattern = "[:,\,/,?,*,<,>,',|,""""]"
    s = objRegExp.Replace(sName, "")
    CheckName = s
End Function

Укажите номер столбца с именами для картинок — указывается порядковый номер столбца на листе, из которого брать имя для сохраняемой картинки. Например, сами картинки в столбце H, а имена для них записаны в столбце B. Надо указать 2. Тогда для картинки в ячейке H3 будет использовано имя, записанное в ячейке В3. Расширение для картинки указывать не надо(например — image1, image2, image_product_sell1 и т.п.).
Если номер не указывать или указать 0 — то имя для картинок будет взято из тех ячеек, в которых находятся эти картинки.
Так же проверяется корректность значений в ячейках, т.к. они могут содержать символы, недопустимые в именах файлов(слеши и пр.). В этом случаи эти символы будут удалены. И если после удаления этих символов значение будет пустым — имена картинкам будут даваться с префиксом «unnamed_» и порядковым номером таких картинок.

Скачать пример

  Tips_Macro_Save_Object_As_Picture.xls (76,0 KiB, 15 154 скачиваний)

Также см.:
Сохранить диаграммы в графический файл
Сохранение выделенного диапазона в графический файл
Как скопировать картинку из примечания?


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

Всем привет.

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

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

Спасибо.

Изменено: nerv14.03.2013 00:43:13

 

Юрий М

Модератор

Сообщений: 60575
Регистрация: 14.09.2012

Контакты см. в профиле

Саш, привет! У Игоря на сайте посмотри — по сохранению у него там было.

 

Сохранить изображение с листа в файл несложно:

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, без использования сторонних библиотек и программ?

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

#4

14.03.2013 20:51:54

Юрий, Игорь, спасибо!  :)

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

Цитата
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

 

EducatedFool

Пользователь

Сообщений: 3631
Регистрация: 23.12.2012

#5

14.03.2013 22:42:14

Цитата
Идея проста как два пальца — сохранить файл как html.

Это я знаю. Но — не подходит.
А как потом разобрать, где какая картинка?

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

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

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

Цитата
Не знаю насколько правильное направление, но есть такие функции у класса StdFunctions, как

Направление правильное, но получить объект типа IPictureDisp из картинки на листе — это такой гемор…
надо много WinAPI использовать (да и, скорее всего, не будет работать при отключеннном ScreenUpdating)
Если кто знает (и пробовал применять) способ преобразования картинки с листа в IPictureDisp — пожалуйста, поделитесь примером.
(я уже и на WinAPI согласен, лишь бы стабильно работало)

Изменено: EducatedFool14.03.2013 22:42:31

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

#6

14.03.2013 23:22:50

Цитата
EducatedFool пишет:
Это я знаю. Но — не подходит.
А как потом разобрать, где какая картинка?

Сохраняет в том порядке, в кот. перебирает в цикле. Последняя картинка — снимок листа. По крайней мере у меня так.

Пример

> 100 kb

Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина — самый громкий звук
https://github.com/nervgh

 

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

Например, один раз при экспорте добавилась «лишняя» первая картинка:

http://ExcelVBA.ru/pictures/20130315-wd8-33kb.jpg

(похоже, картинка из активной ячейки выгружается первой, дополнительно к остальным картинкам)

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

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

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

PS: Подождём визита в эту тему Владимира (ZVI) — у него на любой вопрос по VBA Excel есть готовое решение, о существовании которого большинство форумчан даже не догадывалось ранее)

Изменено: EducatedFool15.03.2013 00:33:54

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

#8

15.03.2013 13:56:23

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

Согласен, что он не надежный, но, глядя на то, как обстоят дела с экспортом изображений, особо вариантов нет.
1. лес Win API
2. чудо диаграммы
3. придумай сам (html etc.)

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

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

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

не всегда есть такая возможность

Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина — самый громкий звук
https://github.com/nervgh

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

#9

21.03.2013 17:48:15

Как оказалось

, сохранить изображение из документа 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

Нюансы: если попытаться открыть (просмотреть) изображение через любой просмотрщик или программу, оно не откроется, но, если импортировать его в ворд, будет отображаться корректно. В деталях пока не разбирался.

Изменено: nerv21.03.2013 17:49:11

Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина — самый громкий звук
https://github.com/nervgh

 

А я всё же через WinAPI решил все делать:

http://excelvba.ru/code/ResizeImages

(картинки с листа сохраняются функцией GdipSaveImageToFile, через буфер обмена)

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

#11

21.03.2013 20:51:20

угу, спасибо. Еще одно спасибо (заочное) товарищу Скрипту с программерс, за хорошую идею.

Пример без 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

 

LightZ

Пользователь

Сообщений: 1748
Регистрация: 22.12.2012

Саш, если я не ошибаюсь, данную библиотеку освоил anvg

(ссылка на источник)

и уже потом поделился с остальными.
А вот

ссылочка

на dll’ку, возможно кому-то понадобиться, т.к. для обработки изображений необходима WIA v2 (пришлось устанавливать, так как у меня изначально была только v1.01)

Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

LightZ, спасибо, Богдан. Я не натыкался на ту ссылку, сразу на инглише гуглил ) Насколько понял, нормальная либа. Поддержка с Windows ME+.

Единственная проблема — сохранить файл на диск из книги/документа.

 

anvg

Пользователь

Сообщений: 11878
Регистрация: 22.12.2012

Excel 2016, 365

Всё же, если необходимо использовать изображение исходного размера (копирование в буфер даёт изображение, которое имеет, как правило, меньшую ширину/высоту в пикселах), то, по-моему мнению, лучше использовать сохранение страницы в файл html. Чтобы однозначно определить нужное изображение необходимо будет задать ему своё имя (допустим mypic1), тогда в коде html файла его можно будет найти по строке
<v:shape id=»mypic1″
и поиском следующей строки
<v:imagedata src=»Страница.files/Книга1_25305_image001.jpg»
найти относительный путь и имя файла-растра.
В случае сохранения только одно листа 2003 и 2010 ведут себя одинаково (рисунки сохраняются в отдельную папку ИмяФайла.files

Изменено: anvg22.03.2013 05:35:18

 

Johny

Пользователь

Сообщений: 2737
Регистрация: 21.12.2012

Попробуй ADODB.Stream

There is no knowledge that is not power

 

nerv

Пользователь

Сообщений: 3071
Регистрация: 22.12.2012

#16

22.03.2013 12:45:12

anvg, спасибо за ответ!

Цитата
anvg пишет:
Чтобы однозначно определить нужное изображение необходимо будет задать ему своё имя (допустим mypic1

я это делал в данной теме

несколькими постами выше

, но смекалки не хватило на

Цитата
anvg пишет:
тогда в коде html файла его можно будет найти по строке
<v:shape id=»mypic1″
и поиском следующей строки
<v:imagedata src=» Страница.files/Книга1_25305_image001.jpg»
найти относительный путь и имя файла-растра.

:)

Johny, можно пример?

Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина — самый громкий звук
https://github.com/nervgh

 

Johny

Пользователь

Сообщений: 2737
Регистрация: 21.12.2012

Вчера написал тестовую программу на 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

 

anvg

Пользователь

Сообщений: 11878
Регистрация: 22.12.2012

Excel 2016, 365

#18

25.03.2013 09:44:43

Цитата
(требуется .NET Framework 4.5)

А на 3.5 уже никак?

 

Johny

Пользователь

Сообщений: 2737
Регистрация: 21.12.2012

#19

25.03.2013 13:25:22

Цитата
anvg пишет:
А на 3.5 уже никак?

Нет, так как в .NET 4.5 добавлен родной zip-архиватор (класс ZipArchive и ZipArchiveEntry).

There is no knowledge that is not power

excel to image

How to save an Excel Range as an Image file (JPG)? Today’s post is inspired by my readers emails. In some of my previous emails I considered other Excel Image scenarios such as Adding Images to Excel using VBA or using the Excel Camera Tool to create an image snapshot in Excel. However today I stumbled across a different scenario: Saving an Excel Range as an Image File.

Excel Range to ImageLet us start with an example. The easiest way to create an image in Excel is to Select an Excel Range, next hit the Copy button from Home ribbon and finally by clicking Paste with Picture.

Seems at first like we are just one step away from saving the image as an image file right?

Excel: Right click only to find... there is no Save As ImageWrong! Only problem being… there is no Save As Image button easily available in Excel!

Of course you might say – why no copy and paste to MS Paint or another Image Editor? Yes that is always an option. But let me show you a much better and dedicated tool for taking Snapshots in any Windows application. Next I will show a way to achieve the task above with a simple VBA Macro.

Snipping Tool

Windows Snipping ToolOne way is to use the almighty Microsoft Snipping Tool which is great for creating image snapshots and saving them as images (PNG files).Windows Snipping Tool ExampleYou can see how the Snipping Tool works easily.

The problem however is that the Snipping Tool is not very precise and often detailed Excel Range images are cumbersome to achieve. This is where as usually we can use a bit of Visual Basic for Applications to automate this task…

Excel to Image with VBA

Now let us create an Image from an Excel Range like a pro. First copy the Excel VBA code below to an existing or new VBA Module:

Sub SelectedRangeToImage()
    Dim tmpChart As Chart, n As Long, shCount As Long, sht As Worksheet, sh As Shape
    Dim fileSaveName As Variant, pic As Variant
    'Create temporary chart as canvas
    Set sht = Selection.Worksheet
    Selection.Copy
    sht.Pictures.Paste.Select
    Set sh = sht.Shapes(sht.Shapes.Count)
    Set tmpChart = Charts.Add
    tmpChart.ChartArea.Clear
    tmpChart.Name = "PicChart" &amp; (Rnd() * 10000)
    Set tmpChart = tmpChart.Location(Where:=xlLocationAsObject, Name:=sht.Name)
    tmpChart.ChartArea.Width = sh.Width
    tmpChart.ChartArea.Height = sh.Height
    tmpChart.Parent.Border.LineStyle = 0
    'Paste range as image to chart
    sh.Copy
    tmpChart.ChartArea.Select
    tmpChart.Paste
    'Save chart image to file
    fileSaveName = Application.GetSaveAsFilename(fileFilter:="Image (*.jpg), *.jpg")
    If fileSaveName &lt;&gt; False Then
      tmpChart.Export Filename:=fileSaveName, FilterName:="jpg"
    End If
    'Clean up
    sht.Cells(1, 1).Activate
    sht.ChartObjects(sht.ChartObjects.Count).Delete
    sh.Delete
End Sub

What does the VBA Macro do? The Sub will do the following

  1. Copy the selected Excel Range and paste it as a Picture

  2. Copy the Picture to an empty Chart

  3. Ask for the destination file name

  4. Save the Chart as a JPG image

Now you may as Why not use VBA to save the pasted Picture as an Image file?. Well, you can’t (not so straight forward at least). The workaround above works pretty well however.

Using the Excel to Image VBA

run excel to image macroFirst select the Excel Range you want to save as an Image. To run the VBA Macro click the Macros button to open the Macros window.

run the excel to image macro 2All that is left is to select the VBA Macro from the Macro window and to hit Run.
excel to image save windowThere may a short pause for the macro to process the image, shortly after the Save As file dialog should appear. Simply select your destination file name and hit Save and that is it!

Save Excel as Static Image Workbook

As usual I am leaving the best for last. Say you want to share an Excel Workbook as readonly. You can try protecting the Password Protecting your Excel documents but the safety is limited if you want to protect your underlying formulas.

excel to image vba macroWhat better way to protect your formulas then to send an Excel Workbook with print screen images of each and every Worksheet? The VBA Macro will additionally save the copy of your file as an XLSX file which means all VBA Macros will be removed as well.

Excel to Static Image Workbook VBA

Below the VBA code snippet to create a copy of your Workbook where every Worksheet is an image copy of the original.

Sub SaveStaticImageWorkbook()
    Dim ws As Worksheet, wb As Workbook, fDialog As FileDialog
    Application.DisplayAlerts = False
    Set wb = Workbooks.Add
    wb.Sheets(1).Name = "Tmp123"
    For Each ws In ThisWorkbook.Worksheets
        ws.Copy After:=wb.Sheets(wb.Sheets.Count)
    Next ws
    'Remove Sheet1
    wb.Sheets("Tmp123").Delete
    For Each ws In wb.Worksheets
        ws.Range(ws.Cells(1, 1), ws.Cells.SpecialCells(xlLastCell)).Copy
        ws.Select
        ws.Cells(1, 1).Select
        ws.Pictures.Paste
        ws.Range(ws.Cells(1, 1), ws.Cells.SpecialCells(xlLastCell)).Clear
    Next ws
    
    Set fDialog = Application.FileDialog(msoFileDialogSaveAs)
    fDialog.Title = "Save Static Workbook"
    fDialog.InitialFileName = ThisWorkbook.Path
    If fDialog.Show = -1 Then
      wb.SaveAs fDialog.SelectedItems(1)
    End If
    wb.Close SaveChanges:=False
    Application.DisplayAlerts = True
End Sub

Great right? I have noticed that in most cases the Image Workbook might however be a bit larger than the original file which has its slight downside. Then again this will depend heavily on the type of Workbook (more formatting larger file size).

Let me know what you think!

Excel VBA, Save Range/Cells as JPEG

Jun 23, 2015 in Excel

In this article I will explain how you can use VBA for Excel to save a range of cells as a JPEG image. Basically what we do is the following:

  1. Create an empty chart in some sheet which is not used.
  2. Copy the cells with the required data as a picture.
  3. Paste the range onto the chart.
  4. Export the table.


Save Range as JPEG:

In this example I will save the range A1:E12 as a JPEG image to the path “D:StuffBusinessTemp”

Excel, VBA, Data to Save as JPEG
This can be done using the code below:

Sub Example1()
Dim i  As Integer
Dim intCount As Integer
Dim objPic As Shape
Dim objChart As Chart
'copy the range as an image
Call Sheet1.Range("A1:E12").CopyPicture(xlScreen, xlPicture)

'remove all previous shapes in sheet2
intCount = Sheet2.Shapes.Count
For i = 1 To intCount
    Sheet2.Shapes.Item(1).Delete
Next i
'create an empty chart in sheet2
Sheet2.Shapes.AddChart
'activate sheet2
Sheet2.Activate
'select the shape in sheet2
Sheet2.Shapes.Item(1).Select
Set objChart = ActiveChart
'paste the range into the chart
objChart.Paste
'save the chart as a JPEG
objChart.Export ("D:StuffBusinessTempExample.Jpeg")
End Sub

Result:

Example
The line below copies the range as an image:

Call Sheet1.Range("A1:E12").CopyPicture(xlScreen, xlPicture)

The for i loop below removes any previous shapes and charts in sheet2:

'remove all previous shapes in sheet2
intCount = Sheet2.Shapes.Count
For i = 1 To intCount
    Sheet2.Shapes.Item(1).Delete
Next i

Basically this should be done on an empty sheet to make sure nothing goes wrong.

The lines below add a new chart and assign it the objChart variable:

'create an empty chart in sheet2
Sheet2.Shapes.AddChart
'activate sheet2
Sheet2.Activate
'select the shape in sheet2
Sheet2.Shapes.Item(1).Select
Set objChart = ActiveChart

The line below pastes the range as a picture onto the chart:

objChart.Paste

The line below saves the chart as a JPEG at the address “D:StuffBusinessTemp”:

objChart.Export ("D:StuffBusinessTempExample.Jpeg")


Remove White Spaces From Image:

As you can see from the resulting image in the previous section, there was a lot of empty space around the final image. The image dimensions are based on the dimensions of the chart object . In order to remove those spaces we must modify the dimensions of the chart to match those of the range. This can be done by adding the lines below to our previous code:

Sub Example2()
Dim i  As Integer
Dim intCount As Integer
Dim objPic As Shape
Dim objChart As Chart
'copy the range as an image
Call Sheet1.Range("A1:E12").CopyPicture(xlScreen, xlPicture)

'remove all previous shapes in sheet2
intCount = Sheet2.Shapes.Count
For i = 1 To intCount
    Sheet2.Shapes.Item(1).Delete
Next i
'create an empty chart in sheet2
Sheet2.Shapes.AddChart
'activate sheet2
Sheet2.Activate
'select the shape in sheet2
Sheet2.Shapes.Item(1).Select
Set objChart = ActiveChart
'paste the range into the chart
Sheet2.Shapes.Item(1).Width = Range("A1:E12").Width
Sheet2.Shapes.Item(1).Height = Range("A1:E12").Height
objChart.Paste
'save the chart as a JPEG
objChart.Export ("D:StuffBusinessTempExample.Jpeg")
End Sub

 Result:

Example


Remove Image Border:

As you can from the images from the previous sections a black border was added to the image. This is due to the chart objects border. In order to remove the border, we would need to remove the chart objects border. This can be done by adding the line below:

Sub Example3()
Dim i  As Integer
Dim intCount As Integer
Dim objPic As Shape
Dim objChart As Chart
'copy the range as an image
Call Sheet1.Range("A1:E12").CopyPicture(xlScreen, xlPicture)

'remove all previous shapes in sheet2
intCount = Sheet2.Shapes.Count
For i = 1 To intCount
    Sheet2.Shapes.Item(1).Delete
Next i
'create an empty chart in sheet2
Sheet2.Shapes.AddChart
'activate sheet2
Sheet2.Activate
'select the shape in sheet2
Sheet2.Shapes.Item(1).Select
Set objChart = ActiveChart
'paste the range into the chart

Sheet2.Shapes.Item(1).Line.Visible = msoFalse
Sheet2.Shapes.Item(1).Width = Range("A1:E12").Width
Sheet2.Shapes.Item(1).Height = Range("A1:E12").Height
objChart.Paste
'save the chart as a JPEG
objChart.Export ("D:StuffBusinessTempExample.Jpeg")
End Sub

Result:

Example

You can download the file and code related to this article from the link below:

  • Range to Jpeg.xlsm

See also:

  • Word VBA, Save Table as JPEG

If you need assistance with your code, or you are looking for a VBA programmer to hire feel free to contact me. Also please visit my website www.software-solutions-online.com

Like this post? Please share to your friends:
  • Vba создание шаблона word
  • Vba создание функции для всего excel
  • Vba создание своей функции excel
  • Vba создание сводных таблиц в excel
  • Vba создание нового файла word