Добрый день уважаемые форумчане. У меня возникла необходимость извлечь (понятное дело программным образом) из файла excel (.xlsm) файл например картинки, которую я туда ранее запихнул. (см. пример) (файл Книга1.xlsm\customUI\images\ttt.jpg ) Не могу понять как это сделать. Может кто подскажет.
Sub Copy_File()
Dim sFileName As String, sNewFileName As String, s As String, s1 As String
sFileName = "C:\TEMP\Книга1.xlsm" 'имя файла для копирования
sNewFileName = "C:\TEMP\Книга1.zip" 'имя копируемого файла. Директория должна существовать
s = "C:\TEMP" '- папка для извлечения файла из архива
s1 = "customUI/images/ttt.jpg" '- распаковываемый файл
If Dir(sFileName, 16) = "" Then MsgBox "Нет такого файла", vbCritical, "Ошибка": Exit Sub
FileCopy sFileName, sNewFileName 'копируем файл
With CreateObject("Shell.Application").Namespace((s)) 'распаковываем
.CopyHere sNewFileName & "\" & s1
End With
End Sub
Ваш вариант не смотрел. В результате получите в папке Temp распакованный файл по тому же пути что и в архиве был customUI\images\ttt.jpg Допишите дальше перемещение ttt.ipg в нужное вам место, и удалить созданный хлам (т.е. Книга1.zip и полностью папку customUI из Temp)
Еще вариант, на случай если первый будет материться. Кстати с этим вариантов на моем втором ноуте w7 office2010 достает файл чистым без подпапок.
Код
Sub Copy_File()
Dim sFileName As String, sNewFileName As String, s As String, s1 As String
Set fso = CreateObject("scripting.filesystemobject")
sFileName = "C:\temp\Книга1.xlsm" 'имя файла для копирования
sNewFileName = "C:\temp\Книга1.zip" 'имя копируемого файла. Директория должна существовать
s = "C:\temp" '- папка для извлечения файла из архива
s1 = "customUI\images\ttt.jpg" '- распаковываемый файл
If Dir(sFileName, 16) = "" Then MsgBox "Нет такого файла", vbCritical, "Ошибка": Exit Sub
fso.CopyFile sFileName, sNewFileName 'копируем файл
With CreateObject("Shell.Application").Namespace((s)) 'распаковываем
.CopyHere sNewFileName & "\" & s1
End With
End Sub
Запилил простенькую программу на VB.NET (расширение поменяйте на EXE), которая показывает содержимое файла (нужна установка .NET Framework 4.6.1). Load File - загружает содержимое в листбокс, отмечаете нужные файлы (пути отсортированы) и жмёте Extract. Файлы распаковываются в папку с программой. Исходный код:
Код
Imports System.IO
Imports System.IO.Compression
Public Class Root
Private Sub btnExtract_Click(sender As Object, e As EventArgs) Handles btnExtract.Click
Dim xlFile = lstFiles.Tag
Using zip = ZipFile.OpenRead(xlFile.ToString())
For Each item In lstFiles.CheckedItems
Dim entry = zip.Entries.Where(Function(t) t.FullName = item.ToString()).First()
entry.ExtractToFile(Path.Combine(Directory.GetCurrentDirectory(), entry.Name))
Next
End Using
MsgBox("Files were extracted", MsgBoxStyle.Information)
End Sub
Private Sub btnLoadFile_Click(sender As Object, e As EventArgs) Handles btnLoadFile.Click
Dim dialog = New OpenFileDialog With
{
.InitialDirectory = Directory.GetCurrentDirectory(),
.Multiselect = False,
.Filter = "Excel Files | *.xlsx;*.xlsm;*.xlsb;*.xlam;*.xltx"
}
If dialog.ShowDialog() = DialogResult.Cancel Then Return
Dim xlFile = dialog.FileName
lstFiles.Tag = xlFile
Using zip = ZipFile.OpenRead(xlFile)
zip.Entries.OrderBy(Function(t) t.FullName).ToList().ForEach(Sub(entry) lstFiles.Items.Add(entry.FullName))
End Using
End Sub
End Class
После изучения всех предложенных вариантов вынужден констатировать, что к сожалению проблема полностью не решается ни одним из предложенных способов. Возможно я не совсем корректно описал задачу. Она выглядит так: Файл excel используется для диалогового окна, где пользователь выбирает по некоторому алгоритму картинку. После выбора эта картинка загружается из базы данных с удаленного сервера. Но для тех случаев, когда в базе не оказывается нужного имиджа, я хочу подсовывать заготовленную картинку - что мол файла нет. Эту картинку я собираюсь хранить в самом файле excel и перед началом работы извлекать из хранилища (в тот же каталог что и файл) и в дальнейшем работать по стандартному алгоритму "подсовывания" картинки по запросу. Просто теперь это будет не картинка загруженная с сервера, а извлеченная из самого файла. Эта картинка нигде не видна, файл excel используется лишь как zip архив, поэтому вариант предложенный уважаемым The_Prist к сожалению не катит
Из всех предложенных вариантов рабочим оказался только второй предложенный уважаемым devilkurs_now. Однако он выводит окно "термометра" при загрузке и работает (у меня) ну очень медленно. Секунд 25. Хотя по идее должно быть на много быстрее. А хотелось бы быстрый и не заметный для пользователя способ извлечения файла. Может что то присоветуете?
vitorian написал: Возможно я не совсем корректно описал задачу.
Возможно, надо сначала воспользоваться головой, а потом пудрать мозги людям (подсказка: вопрос чуть менее чем полностью не соответствует вашей "корректной" задаче).
Цитата
vitorian написал: Эту картинку я собираюсь хранить в самом файле excel
Способ хранения файла в "файле" самый идеальный для той задачи которую я решаю. Потому что этот файл рассылается различным пользователям как аналог любого экзешника. В нем реализован интерфейс некой программы. Хранение картинки в отдельном файле предполагает отсылку двух файлов, с указанием где располагать файл картинки и прочий не нужный геморрой. Такой же способ предполагает все необходимые части хранить в одном контейнере.
Цитата
SuperCat написал: Возможно, надо сначала воспользоваться головой, а потом пудрать мозги людям (подсказка: вопрос чуть менее чем полностью не соответствует вашей "корректной" задаче).
Возможно вначале следует внимательно прочитать общую задачу прежде чем с валить с больной головы на здоровую.
Бред какой-то. Вам предложили несколько вариантов, а потом вы начинаете "уточнять", говорить про некий "интерфейс программы". Причём тут экзешник, Эксель и картинка?
Уточнять пришлось, что бы улучшить понимание задачи, хотя изначально описана предельно просто. Есть контейнер (в данном случае файл экселя) нужно извлечь из него файл. Если вы попробуете внедрить в корпоративной сети новую программу, без административных прав, я посмотрю как вы будете штатными способами инсталлировать ее на другие компы. хрен у вас получится. А эксельный файл - отличное средство для быстрого решения небольшой задачи. Офиис установлен у всех значит эксель запустится у каждого. И если для ее "инсталляции" требуется еще ряд вспомогательных файлов, то почему бы не воспользоваться экселем как контейнером для других файлов. Сервис от этого только выигрывает.
У EducatedFool был код как вытянуть картинку из ячеек листа - т.е. можно хранить файл картинки как данные на листе (скрытом или суперскрытом), кодом выгрузить её например в temp юзера, затем оттуда использовать как угодно. Так не будет лишней копии файла - хотя в принципе ведь можно эту копию сразу убить и в дальнейшем не делать, если картинка уже извлечена в temp.
Hugo написал: т.е. можно хранить файл картинки как данные на листе (скрытом или суперскрытом)
Согласен. Можно и так хранить. Просто у меня и без того куча вспомогательных скрытых листов. Не хотелось их множить. Но возможно придется пойти этим путем. В данном случае интерес остается чисто академический. Можно ли быстро и не заметно для юзера извлечь файл? К тому же может потребоваться не только картинка, но и файл другого формата.
Доброе время суток Ссылка на разработку Игоря по хранению произвольных файлов Прикрепление и извлечение различных файлов из книги Excel. А можно, используя коллекцию CustomProperties листа, сохранять и читать любой байт-массив, коим и является файл.
vitorian написал: Если из названия темы проблема может трактоваться двояко, то из ее описания разве не понятно о чем речь?
Прежде всего проблема должна быть понятна из самого названия. А вот в описании уже детали. А прочитав Ваше название, можно что предположить? - человеку требуется извлечь или текст макроса или форму - ведь чаще всего именно в xlsm их можно найти.