axtrace Пользователь Сообщений: 23 |
Добрый день! Проблема в следующем: все данные с листа помещаю в массив, чтобы их быстрее обработать. На малых объемах все работает хорошо. На больших, близких к граничным, вылезает ошибка «RunTime Error 7 — Out of Memory». Она вылезает или на ReDim массива, или на присвоении массиву диапазона с листа. Что странно, так это ошибка не вылезает, если использую константу в 1 500 000 (строк), а если через переменную передаю 1048574 (строк), то вылезает. Это и взрывает мне мозг. Запускаю функцию Sub StartTransferData() в модуле m2_Main2 в файле (48 Мб): https://docs.google.com/file/d/0B_GHN7yiYuxELWVSSmJIM3VUczg/edit?usp=sharing весит много, поэтому через гугл драйв. Подскажите, пожалуйста, в чем может быть дело и как бороться. Спасибо Изменено: axtrace — 01.02.2013 18:08:48 |
LastRow=1’048’574, LastCol=16’384 всего 17’179’836’416 ячеек; даже всего по одному байту на ячейку — нужно не менее 16Г памяти только на массив. Изменено: Михаил С. — 01.02.2013 18:54:26 |
|
EducatedFool Пользователь Сообщений: 3632 |
#3 01.02.2013 18:56:43 Возможно, дело и не в объёме памяти, требуемой для массива,
А в коде написано 150 000 PS: Через Redim можно изменять только верхнюю размерность массива Изменено: EducatedFool — 01.02.2013 19:01:17 |
||
axtrace Пользователь Сообщений: 23 |
#4 01.02.2013 19:00:51
а что такое верхняя размерность массива?
нет, не заработает. я ее специально добавил, чтобы показать, что если указывать размеры как числа, то все ок. |
||||
ikki Пользователь Сообщений: 9709 |
#5 01.02.2013 19:04:27
поправка. фрилансер Excel, VBA — контакты в профиле |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#6 01.02.2013 19:05:55
А Вы попробуйте присвоить LastRow значение = 1048574. И LastColumn = 15. Первую строку с ReDim Отключите. Что получится? |
||
ikki Пользователь Сообщений: 9709 |
#7 01.02.2013 19:14:52 имхо, 48мб качать никто не будет. кстати, размеры массива вообще нет нужды определять явно.
фрилансер Excel, VBA — контакты в профиле |
||
axtrace Пользователь Сообщений: 23 |
#8 01.02.2013 19:17:50
Получилось, что при первом вызове функции getArrayFromSheet — той, в которой этот ReDim содержиться — проходит все успешно, но во втором вызове — я несколько массивов формирую с разных листов — опять вылетает та же ошибка. Хотя там точно также присваивается LastRow значение = 1048574. И LastColumn = 15 |
||
Михаил С. Пользователь Сообщений: 10514 |
#9 01.02.2013 19:20:09
Известно — число столбцов на листе Прикрепленные файлы
|
||
ikki Пользователь Сообщений: 9709 |
#10 01.02.2013 19:21:51
нет. фрилансер Excel, VBA — контакты в профиле |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
Утечка памяти? Попробуйте убить массив. |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#12 01.02.2013 19:24:24
Михаил, не совсем так: это последняя ячейка (номер столбца) по второй строке. |
||
axtrace Пользователь Сообщений: 23 |
#13 01.02.2013 19:24:53
может быть. а как убивают массивы? nArray = tSheet.Range(tSheet.Cells(1, 1), tSheet.Cells(LastRow, LastCol)) |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
Вы сначала объясните — зачем дважды ReDim с одним и тем же nArray? |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
#15 01.02.2013 19:37:27 Попробуйте объявлять процедуру так:
и раскомментируйте строки с объявлением массива и назначением его через функцию. Или массив объявите глобально. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||
ikki Пользователь Сообщений: 9709 |
#16 01.02.2013 19:38:03 вообще-то странно
вполне штатно — в диспетчере задач при пошаговом режиме выделение памяти увеличивается по 150+ метров… по завершении процедуры — всё самоубивается (массив локальный). фрилансер Excel, VBA — контакты в профиле |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#17 01.02.2013 19:39:48 Саш, да вообще нужно, как ты советовал:
|
||
axtrace Пользователь Сообщений: 23 |
#18 01.02.2013 19:42:40
Первый — для примера. На нем не вылезает ошибка. |
||||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#19 01.02.2013 19:44:42
Так и объявляйте сразу динамический массив (см. мой пост выше) — и ReDim’мить не придётся. |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#20 01.02.2013 19:45:30
Неправда — совсем разные размеры. |
||
axtrace Пользователь Сообщений: 23 |
#21 01.02.2013 19:47:50
то есть просто убрать ReDim? Я так сделал, у меня в массив записалось <Out of memory>, программа благополучно продолжила работать, но вылезла ошибка о несуществовании объекта в дальнейшем, при попытке перенести данные из этого массива в другой |
||
axtrace Пользователь Сообщений: 23 |
#22 01.02.2013 19:50:52
я опечатался, вместо 1 500 000 указал 150 000. В файле уже исправил, все равно этот ReDim берет, на втором — ошибка |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#23 01.02.2013 19:58:48
Объявите массив, как указано, и присвойте ему значения из диапазона листа — никакой ошибки быть не должно. Не «просто убрать RedIm», а записать: массив = … |
||
axtrace Пользователь Сообщений: 23 |
#24 01.02.2013 19:59:17
может быть это ограничение разметки памяти в vba? |
||
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
Я полагаю проблема в том, что массив передается в процедуру ссылкой. А в этом случае память не высвобождается — VBA считает, что мы вроде как далее будем использовать переменную. И при повторном обращении с передачей ссылки у нас выделенный размер памяти может «слегка» увеличиватся. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
Михаил С. Пользователь Сообщений: 10514 |
#26 01.02.2013 21:52:01 А мне кажется, дело в простой нехватке физической памяти. Например, такой массив
на моем компе (win7, off 2010, 2 G) срабатывает, а такой
— «RunTime Error 7 — Out of Memory» |
||||
axtrace Пользователь Сообщений: 23 |
#27 01.02.2013 22:00:03
там же только адрес, откуда вызывается и адреса памяти массивов (по ссылке передаются параметры функции). это вроде бы немного. |
||
axtrace Пользователь Сообщений: 23 |
#28 01.02.2013 22:01:35
странно. у меня win7, off2010, 4Gb |
||
axtrace Пользователь Сообщений: 23 |
попробую я, в общем, делать кусками. Брать массив тысяч в 100 строк, преобразовывать его, записывать на новый лист, переходить к следующим 100 тыс. строк… Время, конечно, увеличится. Но хоть какое-то решение у меня будет. все большое спасибо за идеи! Надеюсь, вам пригодится где-нибудь когда-нибудь |
SvetaS_love Пользователь Сообщений: 132 |
#30 14.07.2015 20:39:10 Добрый День!
Как решили прошлую проблему? одинокий странник |
||
Return to VBA Code Examples
In this Article
- Causes of Out of Memory Error
- Preventing an Out Of Memory Error
- Release Objects
- Make Sure Only one Instance of Excel is Running
- Check the Size of your Excel file
- Other ways to Check Memory
This tutorial will explain the VBA Out of Memory Error.
The VBA Out of Memory error occurs when Excel has used all the resources of your machine while running a macro and literally runs out of memory to carry on calculating or running code. This could occur when you have a lot of applications running and try to run a large macro in Excel, or perhaps when you have created a perpetual loop in Excel in error.
(See our Error Handling Guide for more information about VBA Errors)
Causes of Out of Memory Error
An out of memory error can occur if one is working with a workbook that contains many worksheets and thousands of rows. If we create a loop that works with a great volume of data, an out of memory error could occur. It could also occur if we are working with multiple objects and set each object with a SET statement, but then do not clear the references to the objects between procedures or loops.
For example, the following loop could definitely cause a memory error if you have multiple files open with multiple sheets.
Sub TestMemory()
Dim wb As Workbook
Dim ws As Worksheet
Dim i As Single
For Each wb In Application.Workbooks
For Each ws In wb.Sheets
Do Until ActiveCell = "A1048576"
ActiveCell = 1 + i
i = i + 1
ActiveCell.Offset(1, 0).Select
Loop
Next ws
Next wb
End Sub
Preventing an Out Of Memory Error
Release Objects
If we are working with Loops and Objects, we need to make sure that we set the Object to NOTHING once it has been used and it no longer needed – this will release memory.
Make Sure Only one Instance of Excel is Running
If we are working with large files and vast amounts of data, check that you do not have multiple sessions of Excel open – it needs to just be open once. A way to check this is to go to the Task Manager and see how many instances of Excel are running.
Press Ctl+Alt+Delete on the Keyboard,
Click on Task Manager and make sure that there is only one instance of Excel running. In the graphic below, there is one instance, with 2 windows.
We can also check in the Task Manager that there are no instance of Excel running in the background (ie not visible).
Scroll down in the Task Manager until you see Background Processes and make sure Excel is not in that list of programs.
Check the Size of your Excel file
Often there are rows and columns that have been accessed below the ones in your worksheets that are actually used. Excel uses memory in these cells – even if those cells are empty. Check the size of the file by pressing CTRL+SHIFT+END on the keyboard to see where your cell pointer lands. If it lands well below the last cell that you are using, make sure you delete all the empty rows and columns above the cell pointer and then re-save the file – this will reduce the size of your Excel file.
Other ways to Check Memory
There are various other ways to free memory in Excel. A good idea is to close Excel if you are not using it, and then open it later – this will free up any memory that Excel is storing as it tends to store memory even when a workbook is not open! Always make sure your version of Office is up to date by checking for Updates on your PC and check for any VBA add-ins that may be being used, but that you are not using – you can uninstall these to free up even more memory.
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More!
I am running VBA code on a large Excel spreadsheet. How do I clear the memory between procedures/calls to prevent an «out of memory» issue occurring?
jordanz
3434 silver badges11 bronze badges
asked Jan 18, 2013 at 10:32
6
The best way to help memory to be freed is to nullify large objects:
Sub Whatever()
Dim someLargeObject as SomeObject
'expensive computation
Set someLargeObject = Nothing
End Sub
Also note that global variables remain allocated from one call to another, so if you don’t need persistence you should either not use global variables or nullify them when you don’t need them any longer.
However this won’t help if:
- you need the object after the procedure (obviously)
- your object does not fit in memory
Another possibility is to switch to a 64 bit version of Excel which should be able to use more RAM before crashing (32 bits versions are typically limited at around 1.3GB).
answered Jan 18, 2013 at 10:36
assyliasassylias
319k78 gold badges658 silver badges776 bronze badges
5
I’ve found a workaround. At first it seemed it would take up more time, but it actually makes everything work smoother and faster due to less swapping and more memory available. This is not a scientific approach and it needs some testing before it works.
In the code, make Excel save the workbook every now and then. I had to loop through a sheet with 360 000 lines and it choked badly. After every 10 000 I made the code save the workbook and now it works like a charm even on a 32-bit Excel.
If you start Task Manager at the same time you can see the memory utilization go down drastically after each save.
answered Nov 20, 2015 at 14:11
7
Answer is you can’t explicitly but you should be freeing memory in your routines.
Some tips though to help memory
- Make sure you set object to null before exiting your routine.
- Ensure you call Close on objects if they require it.
- Don’t use global variables unless absolutely necessary
I would recommend checking the memory usage after performing the routine again and again you may have a memory leak.
answered Jan 18, 2013 at 10:39
DreamwalkerDreamwalker
3,0324 gold badges30 silver badges60 bronze badges
Found this thread looking for a solution to my problem. Mine required a different solution that I figured out that might be of use to others. My macro was deleting rows, shifting up, and copying rows to another worksheet. Memory usage was exploding to several gigs and causing «out of memory» after processing around only 4000 records. What solved it for me?
application.screenupdating = false
Added that at the beginning of my code (be sure to make it true again, at the end)
I knew that would make it run faster, which it did.. but had no idea about the memory thing.
After making this small change the memory usage didn’t exceed 135 mb. Why did that work? No idea really. But it’s worth a shot and might apply to you.
answered Mar 8, 2019 at 6:53
If you operate on a large dataset, it is very possible that arrays will be used.
For me creating a few arrays from 500 000 rows and 30 columns worksheet caused this error. I solved it simply by using the line below to get rid of array which is no longer necessary to me, before creating another one:
Erase vArray
Also if only 2 columns out of 30 are used, it is a good idea to create two 1-column arrays instead of one with 30 columns. It doesn’t affect speed, but there will be a difference in memory usage.
answered Sep 16, 2017 at 1:11
I had a similar problem that I resolved myself…. I think it was partially my code hogging too much memory while too many «big things»
in my application — the workbook goes out and grabs another departments «daily report».. and I extract out all the information our team needs (to minimize mistakes and data entry).
I pull in their sheets directly… but I hate the fact that they use Merged cells… which I get rid of (ie unmerge, then find the resulting blank cells, and fill with the values from above)
I made my problem go away by
a)unmerging only the «used cells» — rather than merely attempting to do entire column… ie finding the last used row in the column, and unmerging only this range (there is literally 1000s of rows on each of the sheet I grab)
b) Knowing that the undo only looks after the last ~16 events… between each «unmerge» — i put 15 events which clear out what is stored in the «undo» to minimize the amount of memory held up (ie go to some cell with data in it.. and copy// paste special value… I was GUESSING that the accumulated sum of 30sheets each with 3 columns worth of data might be taxing memory set as side for undoing
Yes it doesn’t allow for any chance of an Undo… but the entire purpose is to purge the old information and pull in the new time sensitive data for analysis so it wasn’t an issue
Sound corny — but my problem went away
answered Sep 24, 2015 at 17:46
1
I was able to fix this error by simply initializing a variable that was being used later in my program. At the time, I wasn’t using Option Explicit in my class/module.
answered Feb 18, 2020 at 20:16
TechFanDanTechFanDan
3,2855 gold badges46 silver badges88 bronze badges
При выполнении макроса или просто работы с большим объемом данных в Exel — вылетает ошибка «Недостаточно памяти» (или «Недостаточно ресурсов», «Out of Memory»). Первым делом мы начинаем смотреть в диспетчере задач, сколько у нас используется памяти. Странно, мы видим, что свободной оперативной памяти предостаточно. Excel съедает не так уж и много памяти. Но почему же вылетает такая ошибка?
Давайте сначала разберемся в памяти. Тогда нам станет почему она заканчивается.
Мы знаем, что в компьютере есть оперативная память, жесткий диск, кэш в процессоре. Это физические устройства, которые находятся в распоряжении операционной системы. Операционная система выделяет необходимый объем памяти для каждого приложения. В диспетчере задач, отображается использование физической оперативной памяти.
Приложения, в том числе Excel, оперирует виртуальной памятью. Что же такое виртуальная память?
Виртуальная память — это объем памяти доступный приложению.
Непонятно? Давайте рассмотрим простой пример.
Возьмем первоклассника в первой четверти. В школьной программе дети изучают счет до десяти. Виртуальная память равна 10. Дети учатся решать примеры и задачи, используя числа до 10. Ребенок с легкостью может решить примеры: 2+5=7, 9-4=5. Но задача 9+4=? становится для него непосильной, потому что переполняется объем виртуальной памяти.
Во второй четверти первоклассники изучают счет до двадцати. Виртуальная память увеличивается с 10 до 20. Наш ребенок может с легкостью решить пример 9+4=13, который в первой четверти вызывал у него затруднения.
Объем физической памяти не связан с понятием виртуальной памяти. Объем задействованных нервных клеток головного мозга ребенка за одни каникулы не увеличился в два раза. При этом виртуальная память первоклассника за четверть выросла в 2 раза, а концу учебного года первоклассники оперируют числами до 100, т.е. виртуальная память вырастает на порядок.
Давайте вернемся к нашему Excel-ю. Теперь мы понимаем, что когда Excel говорит, что у него заканчивается виртуальная память, он сообщает, что заканчивается его внутренняя память. О реальной физической оперативной памяти, Excel знает ровно столько, сколько знает (а точнее не знает) наше самосознание о нашем мозге. Вы можете запускать приложение Excel и открывать файлы, как на мощных компьютерах, так и на стареньких слабеньких компьютерах. Правда работать все будет с разной производительностью. Поэтому заглядывать в диспетчер задач, в данном случае не имеет особого смысла.
Объем виртуальной памяти Excel по данным MSDN
Для 64-разрядной версии Excel 2010 не действует ограничение в 2 Gb Microsoft Excel 2007 2Gb Microsoft Excel 2003 1Gb Microsoft Excel 2002 128Mb Microsoft Excel 2000 64Mb
Почему же происходит переполнение виртуальной памяти?
Следует помнить, когда мы запускаем Excel, мы уже занимаем определенный объем виртуальной памяти. Под открытие файлов, надстроек, библиотек нам остается меньше максимально доступного объема памяти.
Очевидная причина переполнения памяти: мы создаем большие массивы, коллекции и заполняем их данными.
Не очевидная причина, когда мы не видим в коде большие массивы и коллекции заполненных данными. Например, мы в коде создаем некий массив данных, заполняем его, а по окончании выполнения процедуры (или функции) не стираем его. Если запускать данный код много раз, то на некоторой итерации может возникнуть переполнение виртуальной памяти. Во избежание подобной ошибки данной ошибки, рекомендую в конце выполнения кода очищать данные:
tmpDim = Empty 'Опустошаем переменную Erase tmpArr 'Стираем массив Set tmpObject = Nothing 'Стираем объект
Вроде бы, в VBA предусмотрена ограничение области видимости переменной, и по завершению выполнения кода процедуры или функции не глобальные переменные перестают существовать. Но к сожалению, при большом повторении процедур, память может переполняется.
Встречаются ситуации, когда за собой не очищают память, другие процедуры, которые не доступны разработчику. В данном случае мы ничего сделать не сможем, за исключением мониторинга объема памяти.
В этом руководстве объясняется ошибка нехватки памяти VBA.
Ошибка VBA Out of Memory возникает, когда Excel использовал все ресурсы вашего компьютера при выполнении макроса и буквально исчерпывает память для продолжения вычислений или выполнения кода. Это могло произойти, когда у вас запущено много приложений и вы пытаетесь запустить большой макрос в Excel, или, возможно, когда вы создали вечный цикл в Excel по ошибке.
(Дополнительную информацию об ошибках VBA см. В нашем Руководстве по обработке ошибок)
Причины ошибки нехватки памяти
Ошибка нехватки памяти может возникнуть, если вы работаете с книгой, содержащей много листов и тысячи строк. Если мы создадим цикл, который работает с большим объемом данных, может возникнуть ошибка нехватки памяти. Это также может произойти, если мы работаем с несколькими объектами и устанавливаем каждый объект с помощью оператора SET, но затем не очищаем ссылки на объекты между процедурами или циклами.
Например, следующий цикл определенно может вызвать ошибку памяти, если у вас открыто несколько файлов с несколькими листами.
1234567891011121314 | Sub TestMemory ()Dim wb As WorkbookDim ws как рабочий листТусклый я как одиночныйДля каждого ББ в Application.WorkbooksДля каждого WS в wb.SheetsСделать до ActiveCell = «A1048576″ActiveCell = 1 + яя = я + 1ActiveCell.Offset (1, 0) .SelectПетляСледующий wsСледующий wbКонец подписки |
Предотвращение ошибки нехватки памяти
Объекты выпуска
Если мы работаем с циклами и объектами, нам нужно убедиться, что мы установили для объекта значение НИЧЕГО после того, как он был использован и больше не нужен — это освободит память.
Программирование на VBA | Генератор кода действительно работает для вас!
Убедитесь, что запущен только один экземпляр Excel
Если мы работаем с большими файлами и огромными объемами данных, убедитесь, что у вас не открыто несколько сеансов Excel — его нужно открыть только один раз. Чтобы проверить это, перейдите в диспетчер задач и посмотрите, сколько экземпляров Excel запущено.
Нажмите Ctrl + Alt + Delete на клавиатуре,
Нажмите на Диспетчер задач и убедитесь, что работает только один экземпляр Excel. На рисунке ниже показан один экземпляр с двумя окнами.
Мы также можем проверить в диспетчере задач, что нет экземпляров Excel, работающих в фоновом режиме (т.е. невидимых).
Прокрутите вниз в диспетчере задач, пока не увидите Фоновые процессы и убедитесь, что Excel нет в этом списке программ.
Проверьте размер вашего файла Excel
Часто строки и столбцы, к которым был получен доступ, располагаются ниже тех, которые используются на ваших листах. Excel использует память в этих ячейках, даже если эти ячейки пусты. Проверьте размер файла, нажав CTRL + SHIFT + END на клавиатуре, чтобы увидеть, где находится указатель вашей ячейки. Если он приземляется значительно ниже последней используемой ячейки, убедитесь, что вы удалили все пустые строки и столбцы над указателем ячейки, а затем повторно сохраните файл — это уменьшит размер вашего файла Excel.
Другие способы проверки памяти
Есть несколько других способов освободить память в Excel. Хорошая идея — закрыть Excel, если вы его не используете, а затем открыть его позже — это освободит всю память, которую хранит Excel, поскольку он имеет тенденцию хранить память, даже когда книга не открыта! Всегда проверяйте актуальность вашей версии Office, проверяя наличие обновлений на вашем компьютере и проверяя любые надстройки VBA, которые могут использоваться, но которые вы не используете — вы можете удалить их, чтобы освободить еще больше памяти.