Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Файл распух до нелогичных размеров. - Мир MS Excel

Старая форма входа
  • Страница 1 из 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • »
Модератор форума: _Boroda_, китин  
Мир MS Excel » Вопросы и решения » Готовые решения » Файл распух до нелогичных размеров. (Один из способов уменьшить размер файла.)
Файл распух до нелогичных размеров.
KuklP Дата: Пятница, 10.09.2010, 15:35 | Сообщение № 1
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
Сразу оговорюсь - макросы не мои. Я только чуточку доработал их для большей универсальности. Итак:
[vba]
Code
Option Explicit
Option Base 1
Sub ReduceSize()
Dim lAntR As Long
Dim iAntK As Integer
Dim aR() As Single
Dim aK() As Single
Dim n As Integer
Dim sFil1 As String
Dim sFil2 As String
Dim sKat As String
Dim sArk As String
Dim sh As Worksheet
Dim nWb As Workbook
Dim i As Integer
      i = 1
       sFil1 = ActiveWorkbook.Name
       sKat = ActiveWorkbook.Path
Set nWb = Workbooks.Add
       sFil2 = ActiveWorkbook.Name
Workbooks(sFil2).SaveAs sKat & "\" & "(2)" & sFil1
       sFil2 = ActiveWorkbook.Name
For Each sh In ThisWorkbook.Sheets
sh.Activate
sArk = ActiveSheet.Name
lAntR = Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
iAntK = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column

ReDim aR(lAntR)
ReDim aK(iAntK)
For n = 1 To lAntR
      aR(n) = Rows(n).RowHeight
       Next n
        For n = 1 To iAntK
      aK(n) = Columns(n).ColumnWidth
       Next n
Application.CutCopyMode = False
Range(Cells(1, 1), Cells(lAntR, iAntK)).Copy
      With nWb
        If .Sheets.Count < i Then
      .Sheets.Add after:=.Sheets(.Sheets.Count)
End If
        .Sheets(i).Name = sArk
       .Sheets(i).Paste
      Application.CutCopyMode = False
For n = 1 To lAntR
.Sheets(i).Rows(n).RowHeight = aR(n)
Next n
For n = 1 To iAntK
.Sheets(i).Columns(n).ColumnWidth = aK(n)
Next n
End With
i = i + 1
Next
Application.DisplayAlerts = False
Call ExportAllStdModules(Workbooks(sFil2))
Workbooks(sFil2).Save
Workbooks(sFil1).Close savechanges:=True
Application.DisplayAlerts = True
End Sub
[/vba]

[vba]
Code
Private Sub ExportAllStdModules(wb As Workbook)
Dim iTempPath As String, iModuleName As String
Dim iVBComponent
With Application
.ScreenUpdating = False
iTempPath = .DefaultFilePath & .PathSeparator
With wb.VBProject.VBComponents
For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
If iVBComponent.Type = 1 Then
iModuleName$ = iTempPath$ & iVBComponent.Name
iVBComponent.Export Filename:=iModuleName$
.Import Filename:=iModuleName$
Kill PathName:=iModuleName$
End If
Next
End With
.ScreenUpdating = True
End With
End Sub
[/vba]

P.S. Думаю, излишним будет напоминать о резервном копировании данных (хотя макрос данные исходной книги никак не затрагивает).


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728
 
Ответить
СообщениеСразу оговорюсь - макросы не мои. Я только чуточку доработал их для большей универсальности. Итак:
[vba]
Code
Option Explicit
Option Base 1
Sub ReduceSize()
Dim lAntR As Long
Dim iAntK As Integer
Dim aR() As Single
Dim aK() As Single
Dim n As Integer
Dim sFil1 As String
Dim sFil2 As String
Dim sKat As String
Dim sArk As String
Dim sh As Worksheet
Dim nWb As Workbook
Dim i As Integer
      i = 1
       sFil1 = ActiveWorkbook.Name
       sKat = ActiveWorkbook.Path
Set nWb = Workbooks.Add
       sFil2 = ActiveWorkbook.Name
Workbooks(sFil2).SaveAs sKat & "\" & "(2)" & sFil1
       sFil2 = ActiveWorkbook.Name
For Each sh In ThisWorkbook.Sheets
sh.Activate
sArk = ActiveSheet.Name
lAntR = Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
iAntK = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column

ReDim aR(lAntR)
ReDim aK(iAntK)
For n = 1 To lAntR
      aR(n) = Rows(n).RowHeight
       Next n
        For n = 1 To iAntK
      aK(n) = Columns(n).ColumnWidth
       Next n
Application.CutCopyMode = False
Range(Cells(1, 1), Cells(lAntR, iAntK)).Copy
      With nWb
        If .Sheets.Count < i Then
      .Sheets.Add after:=.Sheets(.Sheets.Count)
End If
        .Sheets(i).Name = sArk
       .Sheets(i).Paste
      Application.CutCopyMode = False
For n = 1 To lAntR
.Sheets(i).Rows(n).RowHeight = aR(n)
Next n
For n = 1 To iAntK
.Sheets(i).Columns(n).ColumnWidth = aK(n)
Next n
End With
i = i + 1
Next
Application.DisplayAlerts = False
Call ExportAllStdModules(Workbooks(sFil2))
Workbooks(sFil2).Save
Workbooks(sFil1).Close savechanges:=True
Application.DisplayAlerts = True
End Sub
[/vba]

[vba]
Code
Private Sub ExportAllStdModules(wb As Workbook)
Dim iTempPath As String, iModuleName As String
Dim iVBComponent
With Application
.ScreenUpdating = False
iTempPath = .DefaultFilePath & .PathSeparator
With wb.VBProject.VBComponents
For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
If iVBComponent.Type = 1 Then
iModuleName$ = iTempPath$ & iVBComponent.Name
iVBComponent.Export Filename:=iModuleName$
.Import Filename:=iModuleName$
Kill PathName:=iModuleName$
End If
Next
End With
.ScreenUpdating = True
End With
End Sub
[/vba]

P.S. Думаю, излишним будет напоминать о резервном копировании данных (хотя макрос данные исходной книги никак не затрагивает).

Автор - KuklP
Дата добавления - 10.09.2010 в 15:35
Alex_ST Дата: Вторник, 01.02.2011, 18:58 | Сообщение № 2
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Код классный! Можно рекомендовать к широкому использованию.
Попробовал на работе с распухшим за несколько лет общим файлом с сотней страниц. Весил 40 метров. Открывался по сети "со скрипом". Теперь весит 12 метров и по сравнению со старым прямо летает.

Зная нелюбовь Сергея (KuklP) к оформительской работе, давно собирался "причесать" классный код, предложенный им: более понятно (на мой взгляд) переобозвать переменные, добавить комментарии с целью повышения его читабельности не слишком искушенными пользователями.
А тут заболел (грипп, зараза!), сижу дома. Подполировал код Сергея. Надеюсь, он не против?
И так:
1. В стандартный модуль разбухшей книги помещаем код:[vba]
Code
Option Explicit
Option Base 1

Sub ReduceSize() ' фитнесс для разбухших файлов
'---------------------------------------------------------------------------------------
' Procedure : ReduceSize
' Author    : KuklP + Alex_ST ("полировка" и комментарии)
' URL       : http://www.excelworld.ru/forum/3-57-1
' Date      : 10.09.2010 + 01.02.2011
' Purpose   : фитнесс для разбухших файлов
'---------------------------------------------------------------------------------------

       Dim LastRow&, LastColumn%
       Dim arrRowsHeight!(), arrColumnsWidth!()
       Dim oldWbName$, newWbName$
       Dim WbPath$, iShtName$
       Dim iSht As Worksheet
       Dim newWb As Workbook
       Dim i%, n%
       WbPath = ActiveWorkbook.Path ' запомним путь к книге
       oldWbName = ActiveWorkbook.Name ' запомним имя старой книги
       Set newWb = Workbooks.Add ' создадим новую книгу (она сразу станет ActiveWorkbook)
       ActiveWorkbook.SaveAs WbPath & "\" & "(NEW) " & oldWbName 'сохраним новую книгу рядом со старой с префиксом к имени "(NEW) "
       newWbName = ActiveWorkbook.Name ' запомним имя новой книги
       i = 1 ' начинаем с первой страницы новой книги
       For Each iSht In ThisWorkbook.Sheets ' цикл по всем листам старой(ThisWorkbook) книги
           iSht.Activate
           iShtName = ActiveSheet.Name
           LastRow = Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row ' последняя строка на листе, содержащая хоть какие-нибудь значения
           LastColumn = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column ' последний столбец на листе, содержащий хоть какие-нибудь значения
           ReDim arrRowsHeight(LastRow)
           ReDim arrColumnsWidth(LastColumn)
           For n = 1 To LastRow ' запомним высоты строк в массив
               arrRowsHeight(n) = Rows(n).RowHeight
           Next n
           For n = 1 To LastColumn ' запомним ширины столбцов в массив
               arrColumnsWidth(n) = Columns(n).ColumnWidth
           Next n
           Application.CutCopyMode = False
           Range(Cells(1, 1), Cells(LastRow, LastColumn)).Copy ' копируем только диапазон, содержащий данные
           With newWb
               If .Sheets.Count < i Then .Sheets.Add after:=.Sheets(.Sheets.Count)
               .Sheets(i).Name = iShtName
               .Sheets(i).Paste ' копируем на страницы новой книги диапазон, содержащий данные
               Application.CutCopyMode = False
               For n = 1 To LastRow ' восстановим высоты строк
                   .Sheets(i).Rows(n).RowHeight = arrRowsHeight(n)
               Next n
               For n = 1 To LastColumn ' восстановим ширины столбцов
                   .Sheets(i).Columns(n).ColumnWidth = arrColumnsWidth(n)
               Next n
           End With
           i = i + 1 ' продолжим на следующей странице новой книги
       Next
       Application.DisplayAlerts = False
       Call ExportAllStdModules(Workbooks(newWbName)) ' скопировать все компоненты VBA в новую книгу
       Workbooks(newWbName).Save ' сохраним новую книгу
       Workbooks(oldWbName).Close SaveChanges:=False ' закроем старую книгу без сохранения изменений
       Application.DisplayAlerts = True
End Sub

Private Sub ExportAllStdModules(wb As Workbook) ' скопировать все компоненты VBA в новую книгу
       Dim iTempPath$, iModuleName$
       Dim iVBComponent
       With Application
           .ScreenUpdating = False
           iTempPath = .DefaultFilePath & .PathSeparator
           With wb.VBProject.VBComponents
               For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
                   If iVBComponent.Type = 1 Then
                       iModuleName$ = iTempPath$ & iVBComponent.Name
                       iVBComponent.Export Filename:=iModuleName$
                       .Import Filename:=iModuleName$
                       Kill PathName:=iModuleName$
                   End If
               Next
           End With
           .ScreenUpdating = True
       End With
End Sub
[/vba]

2. Выполняем макрос ReduceSize
3. После выполнения работы макроса рядом с распухшим файлом будет создан такой же по содержанию, но "похудевший" новый файл с префиксом (NEW).



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеКод классный! Можно рекомендовать к широкому использованию.
Попробовал на работе с распухшим за несколько лет общим файлом с сотней страниц. Весил 40 метров. Открывался по сети "со скрипом". Теперь весит 12 метров и по сравнению со старым прямо летает.

Зная нелюбовь Сергея (KuklP) к оформительской работе, давно собирался "причесать" классный код, предложенный им: более понятно (на мой взгляд) переобозвать переменные, добавить комментарии с целью повышения его читабельности не слишком искушенными пользователями.
А тут заболел (грипп, зараза!), сижу дома. Подполировал код Сергея. Надеюсь, он не против?
И так:
1. В стандартный модуль разбухшей книги помещаем код:[vba]
Code
Option Explicit
Option Base 1

Sub ReduceSize() ' фитнесс для разбухших файлов
'---------------------------------------------------------------------------------------
' Procedure : ReduceSize
' Author    : KuklP + Alex_ST ("полировка" и комментарии)
' URL       : http://www.excelworld.ru/forum/3-57-1
' Date      : 10.09.2010 + 01.02.2011
' Purpose   : фитнесс для разбухших файлов
'---------------------------------------------------------------------------------------

       Dim LastRow&, LastColumn%
       Dim arrRowsHeight!(), arrColumnsWidth!()
       Dim oldWbName$, newWbName$
       Dim WbPath$, iShtName$
       Dim iSht As Worksheet
       Dim newWb As Workbook
       Dim i%, n%
       WbPath = ActiveWorkbook.Path ' запомним путь к книге
       oldWbName = ActiveWorkbook.Name ' запомним имя старой книги
       Set newWb = Workbooks.Add ' создадим новую книгу (она сразу станет ActiveWorkbook)
       ActiveWorkbook.SaveAs WbPath & "\" & "(NEW) " & oldWbName 'сохраним новую книгу рядом со старой с префиксом к имени "(NEW) "
       newWbName = ActiveWorkbook.Name ' запомним имя новой книги
       i = 1 ' начинаем с первой страницы новой книги
       For Each iSht In ThisWorkbook.Sheets ' цикл по всем листам старой(ThisWorkbook) книги
           iSht.Activate
           iShtName = ActiveSheet.Name
           LastRow = Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row ' последняя строка на листе, содержащая хоть какие-нибудь значения
           LastColumn = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column ' последний столбец на листе, содержащий хоть какие-нибудь значения
           ReDim arrRowsHeight(LastRow)
           ReDim arrColumnsWidth(LastColumn)
           For n = 1 To LastRow ' запомним высоты строк в массив
               arrRowsHeight(n) = Rows(n).RowHeight
           Next n
           For n = 1 To LastColumn ' запомним ширины столбцов в массив
               arrColumnsWidth(n) = Columns(n).ColumnWidth
           Next n
           Application.CutCopyMode = False
           Range(Cells(1, 1), Cells(LastRow, LastColumn)).Copy ' копируем только диапазон, содержащий данные
           With newWb
               If .Sheets.Count < i Then .Sheets.Add after:=.Sheets(.Sheets.Count)
               .Sheets(i).Name = iShtName
               .Sheets(i).Paste ' копируем на страницы новой книги диапазон, содержащий данные
               Application.CutCopyMode = False
               For n = 1 To LastRow ' восстановим высоты строк
                   .Sheets(i).Rows(n).RowHeight = arrRowsHeight(n)
               Next n
               For n = 1 To LastColumn ' восстановим ширины столбцов
                   .Sheets(i).Columns(n).ColumnWidth = arrColumnsWidth(n)
               Next n
           End With
           i = i + 1 ' продолжим на следующей странице новой книги
       Next
       Application.DisplayAlerts = False
       Call ExportAllStdModules(Workbooks(newWbName)) ' скопировать все компоненты VBA в новую книгу
       Workbooks(newWbName).Save ' сохраним новую книгу
       Workbooks(oldWbName).Close SaveChanges:=False ' закроем старую книгу без сохранения изменений
       Application.DisplayAlerts = True
End Sub

Private Sub ExportAllStdModules(wb As Workbook) ' скопировать все компоненты VBA в новую книгу
       Dim iTempPath$, iModuleName$
       Dim iVBComponent
       With Application
           .ScreenUpdating = False
           iTempPath = .DefaultFilePath & .PathSeparator
           With wb.VBProject.VBComponents
               For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
                   If iVBComponent.Type = 1 Then
                       iModuleName$ = iTempPath$ & iVBComponent.Name
                       iVBComponent.Export Filename:=iModuleName$
                       .Import Filename:=iModuleName$
                       Kill PathName:=iModuleName$
                   End If
               Next
           End With
           .ScreenUpdating = True
       End With
End Sub
[/vba]

2. Выполняем макрос ReduceSize
3. После выполнения работы макроса рядом с распухшим файлом будет создан такой же по содержанию, но "похудевший" новый файл с префиксом (NEW).

Автор - Alex_ST
Дата добавления - 01.02.2011 в 18:58
KuklP Дата: Вторник, 01.02.2011, 19:28 | Сообщение № 3
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
Quote (Alex_ST)
Надеюсь, он не против?

Привет, Леш. С чего бы я был против? Для того и выкладывал, чтоб все пользовались. И вообще, я не раз и на разных форумах выказывал свою нелюбовь к скрытию, запароливанию и т.д. То, что создано, должно работать и приносить пользу. И чем большую, тем лучше:-)
Выздоравливай, давай!


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728


Сообщение отредактировал KuklP - Вторник, 01.02.2011, 19:32
 
Ответить
Сообщение
Quote (Alex_ST)
Надеюсь, он не против?

Привет, Леш. С чего бы я был против? Для того и выкладывал, чтоб все пользовались. И вообще, я не раз и на разных форумах выказывал свою нелюбовь к скрытию, запароливанию и т.д. То, что создано, должно работать и приносить пользу. И чем большую, тем лучше:-)
Выздоравливай, давай!

Автор - KuklP
Дата добавления - 01.02.2011 в 19:28
Alex_ST Дата: Вторник, 01.02.2011, 19:36 | Сообщение № 4
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Привет, Серёга!
Рад, что ты ответил. Всё-таки мнение автора - главное. Хотя я в общем-то в твоём "одобрямсе" и не сомневался. Но всё-таки...
Всё. Больше в теме на флудим. Обсуждение здесь - это правильно. А общение - флуд.



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Вторник, 01.02.2011, 19:38
 
Ответить
СообщениеПривет, Серёга!
Рад, что ты ответил. Всё-таки мнение автора - главное. Хотя я в общем-то в твоём "одобрямсе" и не сомневался. Но всё-таки...
Всё. Больше в теме на флудим. Обсуждение здесь - это правильно. А общение - флуд.

Автор - Alex_ST
Дата добавления - 01.02.2011 в 19:36
KuklP Дата: Пятница, 18.02.2011, 10:27 | Сообщение № 5
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
KuklP, Черт, в макросе досадная ошибка.
Вместо
[vba]
Код
With newWb        
       If .Sheets.Count < i Then .Sheets.Add after:=.Sheets.Count
[/vba]
надо
[vba]
Код
With newWb
       If .Sheets.Count < i Then   .Sheets.Add after:=.Sheets(.Sheets.Count)
[/vba]
Подожду кого-нить из модеров, попрошу исправить, а то меня не пускает редактировать


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728


Сообщение отредактировал KuklP - Пятница, 18.02.2011, 10:36
 
Ответить
СообщениеKuklP, Черт, в макросе досадная ошибка.
Вместо
[vba]
Код
With newWb        
       If .Sheets.Count < i Then .Sheets.Add after:=.Sheets.Count
[/vba]
надо
[vba]
Код
With newWb
       If .Sheets.Count < i Then   .Sheets.Add after:=.Sheets(.Sheets.Count)
[/vba]
Подожду кого-нить из модеров, попрошу исправить, а то меня не пускает редактировать

Автор - KuklP
Дата добавления - 18.02.2011 в 10:27
Hugo Дата: Пятница, 18.02.2011, 11:09 | Сообщение № 6
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3252
Репутация: 707 ±
Замечаний: 0% ±

2019
Исправил.


excel@nxt.ru
webmoney: E265281470651 Z422237915069
 
Ответить
СообщениеИсправил.

Автор - Hugo
Дата добавления - 18.02.2011 в 11:09
KuklP Дата: Пятница, 18.02.2011, 11:22 | Сообщение № 7
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
Спасибо, Игорь. Что бы я без тебя...:-)


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728
 
Ответить
СообщениеСпасибо, Игорь. Что бы я без тебя...:-)

Автор - KuklP
Дата добавления - 18.02.2011 в 11:22
Alex_ST Дата: Пятница, 18.02.2011, 15:40 | Сообщение № 8
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Я тоже наткнулся я на эти грабли, когда пытался чужой многостраничный файл "похудеть", но тогда просто закомментировал так:
[vba]
Код
If .Sheets.Count < i Then .Sheets.Add ' after:=.Sheets.Count
[/vba], т.к. было нужно срочно и был "завал" на работе. Решил разобраться потом и забыл... sad

А вот на днях на другие "грабли" напоролся: проблема с элементами OLEObject на листе - не переносятся, гады.
Правда, это было ближе к концу рабочего дня, а перегружать Ёксель я не пробовал (опять "завал")... И тоже отложил "разбор полётов". Может, перед выполнением макроса режим конструктора включить? Надо подуамть...



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Пятница, 18.02.2011, 15:43
 
Ответить
СообщениеЯ тоже наткнулся я на эти грабли, когда пытался чужой многостраничный файл "похудеть", но тогда просто закомментировал так:
[vba]
Код
If .Sheets.Count < i Then .Sheets.Add ' after:=.Sheets.Count
[/vba], т.к. было нужно срочно и был "завал" на работе. Решил разобраться потом и забыл... sad

А вот на днях на другие "грабли" напоролся: проблема с элементами OLEObject на листе - не переносятся, гады.
Правда, это было ближе к концу рабочего дня, а перегружать Ёксель я не пробовал (опять "завал")... И тоже отложил "разбор полётов". Может, перед выполнением макроса режим конструктора включить? Надо подуамть...

Автор - Alex_ST
Дата добавления - 18.02.2011 в 15:40
KuklP Дата: Пятница, 18.02.2011, 23:59 | Сообщение № 9
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
А еще он не перенесет макросы из модулей листов. Можно разрешить, но перенесет как классы. А OLEObject в новом файле сохранившие ссылки на старый файл тебе нужны? Отож. А если еще и куча форм в файле, грабли обеспечены. Я уже неоднократно утверждал, что универсальные макросы всех времен и народов - это не мое:-) Я больше на злобу дня...


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728
 
Ответить
СообщениеА еще он не перенесет макросы из модулей листов. Можно разрешить, но перенесет как классы. А OLEObject в новом файле сохранившие ссылки на старый файл тебе нужны? Отож. А если еще и куча форм в файле, грабли обеспечены. Я уже неоднократно утверждал, что универсальные макросы всех времен и народов - это не мое:-) Я больше на злобу дня...

Автор - KuklP
Дата добавления - 18.02.2011 в 23:59
Alex_ST Дата: Суббота, 19.02.2011, 18:52 | Сообщение № 10
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Quote (KuklP)
А еще он не перенесет макросы из модулей листов

Я это тоже заметил, но разбираться было некогда - ручками перенёс вместе с OLEObject-ами листа.
Для меня это вообще наикрутейший облом, т.к. я как раз люблю писАть так, чтобы было как можно меньше связей между листами. При таком стиле программирования можно лист без проблем копировать в другую книгу и всё будет работать, как, например, в моём "удобном автофильтре" ... Конечно, это ведёт к избыточности кода, зато удобно.



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Суббота, 19.02.2011, 21:44
 
Ответить
Сообщение
Quote (KuklP)
А еще он не перенесет макросы из модулей листов

Я это тоже заметил, но разбираться было некогда - ручками перенёс вместе с OLEObject-ами листа.
Для меня это вообще наикрутейший облом, т.к. я как раз люблю писАть так, чтобы было как можно меньше связей между листами. При таком стиле программирования можно лист без проблем копировать в другую книгу и всё будет работать, как, например, в моём "удобном автофильтре" ... Конечно, это ведёт к избыточности кода, зато удобно.

Автор - Alex_ST
Дата добавления - 19.02.2011 в 18:52
Alex_ST Дата: Понедельник, 21.02.2011, 11:06 | Сообщение № 11
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Сергей, а почему собственно в Private Sub ExportAllStdModules ты ограничился только копированием стандартных модулей?
Если я правильно понял, то твой код
[vba]
Код
If iVBComponent.Type = 1 Then
[/vba] это то же самое, что
[vba]
Код
If iVBComponent.Type = vbext_ct_StdModule Then
[/vba]
А почему нельзя копировать точно также и модули классов (Type = vbext_ct_ClassModule = 2), модули форм (Type = vbext_ct_MSForm = 3)?

К стати, а вот здесь написано:
vbext_ct_Document (100): One of the Sheet modules or the ThisWorkbook module
что-то я не понял, модули листов разве не модули класса?



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеСергей, а почему собственно в Private Sub ExportAllStdModules ты ограничился только копированием стандартных модулей?
Если я правильно понял, то твой код
[vba]
Код
If iVBComponent.Type = 1 Then
[/vba] это то же самое, что
[vba]
Код
If iVBComponent.Type = vbext_ct_StdModule Then
[/vba]
А почему нельзя копировать точно также и модули классов (Type = vbext_ct_ClassModule = 2), модули форм (Type = vbext_ct_MSForm = 3)?

К стати, а вот здесь написано:
vbext_ct_Document (100): One of the Sheet modules or the ThisWorkbook module
что-то я не понял, модули листов разве не модули класса?

Автор - Alex_ST
Дата добавления - 21.02.2011 в 11:06
KuklP Дата: Понедельник, 21.02.2011, 11:41 | Сообщение № 12
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
См. ответ от Дата: Пятница, 18.02.2011, 23:59.
Закомментируй так и посмотри, что выйдет:
[vba]
Код
For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
'If iVBComponent.Type = 1 Then
iModuleName$ = iTempPath$ & iVBComponent.Name
iVBComponent.Export Filename:=iModuleName$
.Import Filename:=iModuleName$
Kill PathName:=iModuleName$
'End If
Next
[/vba]


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728


Сообщение отредактировал KuklP - Понедельник, 21.02.2011, 11:44
 
Ответить
СообщениеСм. ответ от Дата: Пятница, 18.02.2011, 23:59.
Закомментируй так и посмотри, что выйдет:
[vba]
Код
For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
'If iVBComponent.Type = 1 Then
iModuleName$ = iTempPath$ & iVBComponent.Name
iVBComponent.Export Filename:=iModuleName$
.Import Filename:=iModuleName$
Kill PathName:=iModuleName$
'End If
Next
[/vba]

Автор - KuklP
Дата добавления - 21.02.2011 в 11:41
KuklP Дата: Понедельник, 21.02.2011, 12:42 | Сообщение № 13
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
Вымучил, так работает:
[vba]
Код
Sub ReduceSize()
      Dim lAntR As Long
      Dim iAntK As Integer
      Dim aR() As Single
      Dim aK() As Single
      Dim n As Integer
      Dim sFil1 As String
      Dim sFil2 As String
      Dim sKat As String
      Dim sArk As String
      Dim sh As Worksheet
      Dim nWb As Workbook
      Dim i As Integer
      i = 1
      sFil1 = ActiveWorkbook.Name
      sKat = ActiveWorkbook.Path
      Set nWb = Workbooks.Add
      sFil2 = ActiveWorkbook.Name
      Workbooks(sFil2).SaveAs sKat & "\" & "(2)" & sFil1
      sFil2 = ActiveWorkbook.Name
      For Each sh In ThisWorkbook.Sheets
          sh.Activate
          sArk = ActiveSheet.Name
          lAntR = Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
          iAntK = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column

          ReDim aR(lAntR)
          ReDim aK(iAntK)
          For n = 1 To lAntR
              aR(n) = Rows(n).RowHeight
          Next n
          For n = 1 To iAntK
              aK(n) = Columns(n).ColumnWidth
          Next n
          Application.CutCopyMode = False
          Range(sh.Cells(1, 1), sh.Cells(lAntR, iAntK)).Copy
          With nWb
              If .Sheets.Count < i Then
                  .Sheets.Add after:=.Sheets(.Sheets.Count)
              End If
              .Sheets(i).Name = sArk
              .Sheets(i).Paste    '([a1])
              Application.CutCopyMode = False
              For n = 1 To lAntR
                  .Sheets(i).Rows(n).RowHeight = aR(n)
              Next n
              For n = 1 To iAntK
                  .Sheets(i).Columns(n).ColumnWidth = aK(n)
              Next n
          End With
          i = i + 1
      Next
      Application.DisplayAlerts = False
      Call ExportAllStdModules(Workbooks(sFil2))
      Workbooks(sFil2).Save
      Workbooks(sFil1).Close savechanges:=True
      Application.DisplayAlerts = True
End Sub
Private Sub ExportAllStdModules(wb As Workbook)
      Dim iTempPath As String, iModuleName As String
      Dim iVBComponent As Object
      Dim a As Boolean
      With Application
          .ScreenUpdating = False
          iTempPath = .DefaultFilePath & .PathSeparator
          With wb.VBProject.VBComponents
              For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
                  iModuleName$ = iTempPath$ & iVBComponent.Name
                  a = CopyModule(iVBComponent.Name, _
                     ThisWorkbook.VBProject, _
                     wb.VBProject, True)
              Next
          End With
          .ScreenUpdating = True
      End With
End Sub

Function CopyModule(ModuleName As String, _
                      FromVBProject, _
                      ToVBProject, _
                      OverwriteExisting As Boolean) As Boolean
      Dim VBComp   As Object 'As VBIDE.VBComponent
      Dim FName$, CompName$, S$
      Dim SlashPos&, ExtPos&
      Dim TempVBComp    'As VBIDE.VBComponent
      Dim vbext_pp_locked As Boolean
      On Error Resume Next
      Set VBComp = FromVBProject.VBComponents(ModuleName)
      If Err.Number <> 0 Then
          CopyModule = False
          Exit Function
      End If
      FName = Environ("Temp") & "\" & ModuleName & ".bas"
      If OverwriteExisting = True Then
          If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
              Err.Clear
              Kill FName
              If Err.Number <> 0 Then
                  CopyModule = False
                  Exit Function
              End If
          End If
          With ToVBProject.VBComponents
              .Remove .Item(ModuleName)
          End With
      Else
          Err.Clear
          Set VBComp = ToVBProject.VBComponents(ModuleName)
          If Err.Number <> 0 Then
              If Err.Number = 9 Then
                  ' module doesn't exist. ignore error.
              Else
                  ' other error. get out with return value of False
                  CopyModule = False
                  Exit Function
              End If
          End If
      End If
      FromVBProject.VBComponents(ModuleName).Export Filename:=FName
      SlashPos = InStrRev(FName, "\")
      ExtPos = InStrRev(FName, ".")
      CompName = Mid(FName, SlashPos + 1, ExtPos - SlashPos - 1)
      Set VBComp = Nothing
      Set VBComp = ToVBProject.VBComponents(CompName)
      If VBComp Is Nothing Then
          ToVBProject.VBComponents.Import Filename:=FName
      Else
          Set TempVBComp = ToVBProject.VBComponents.Import(FName)
          ' TempVBComp is source module
          With VBComp.CodeModule
              .DeleteLines 1, .CountOfLines
              S = TempVBComp.CodeModule.Lines(1, TempVBComp.CodeModule.CountOfLines)
              .InsertLines 1, S
          End With
          On Error GoTo 0
          ToVBProject.VBComponents.Remove TempVBComp
      End If
      Kill FName
      CopyModule = True
End Function
[/vba]


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728


Сообщение отредактировал KuklP - Понедельник, 21.02.2011, 13:19
 
Ответить
СообщениеВымучил, так работает:
[vba]
Код
Sub ReduceSize()
      Dim lAntR As Long
      Dim iAntK As Integer
      Dim aR() As Single
      Dim aK() As Single
      Dim n As Integer
      Dim sFil1 As String
      Dim sFil2 As String
      Dim sKat As String
      Dim sArk As String
      Dim sh As Worksheet
      Dim nWb As Workbook
      Dim i As Integer
      i = 1
      sFil1 = ActiveWorkbook.Name
      sKat = ActiveWorkbook.Path
      Set nWb = Workbooks.Add
      sFil2 = ActiveWorkbook.Name
      Workbooks(sFil2).SaveAs sKat & "\" & "(2)" & sFil1
      sFil2 = ActiveWorkbook.Name
      For Each sh In ThisWorkbook.Sheets
          sh.Activate
          sArk = ActiveSheet.Name
          lAntR = Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
          iAntK = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column

          ReDim aR(lAntR)
          ReDim aK(iAntK)
          For n = 1 To lAntR
              aR(n) = Rows(n).RowHeight
          Next n
          For n = 1 To iAntK
              aK(n) = Columns(n).ColumnWidth
          Next n
          Application.CutCopyMode = False
          Range(sh.Cells(1, 1), sh.Cells(lAntR, iAntK)).Copy
          With nWb
              If .Sheets.Count < i Then
                  .Sheets.Add after:=.Sheets(.Sheets.Count)
              End If
              .Sheets(i).Name = sArk
              .Sheets(i).Paste    '([a1])
              Application.CutCopyMode = False
              For n = 1 To lAntR
                  .Sheets(i).Rows(n).RowHeight = aR(n)
              Next n
              For n = 1 To iAntK
                  .Sheets(i).Columns(n).ColumnWidth = aK(n)
              Next n
          End With
          i = i + 1
      Next
      Application.DisplayAlerts = False
      Call ExportAllStdModules(Workbooks(sFil2))
      Workbooks(sFil2).Save
      Workbooks(sFil1).Close savechanges:=True
      Application.DisplayAlerts = True
End Sub
Private Sub ExportAllStdModules(wb As Workbook)
      Dim iTempPath As String, iModuleName As String
      Dim iVBComponent As Object
      Dim a As Boolean
      With Application
          .ScreenUpdating = False
          iTempPath = .DefaultFilePath & .PathSeparator
          With wb.VBProject.VBComponents
              For Each iVBComponent In ThisWorkbook.VBProject.VBComponents
                  iModuleName$ = iTempPath$ & iVBComponent.Name
                  a = CopyModule(iVBComponent.Name, _
                     ThisWorkbook.VBProject, _
                     wb.VBProject, True)
              Next
          End With
          .ScreenUpdating = True
      End With
End Sub

Function CopyModule(ModuleName As String, _
                      FromVBProject, _
                      ToVBProject, _
                      OverwriteExisting As Boolean) As Boolean
      Dim VBComp   As Object 'As VBIDE.VBComponent
      Dim FName$, CompName$, S$
      Dim SlashPos&, ExtPos&
      Dim TempVBComp    'As VBIDE.VBComponent
      Dim vbext_pp_locked As Boolean
      On Error Resume Next
      Set VBComp = FromVBProject.VBComponents(ModuleName)
      If Err.Number <> 0 Then
          CopyModule = False
          Exit Function
      End If
      FName = Environ("Temp") & "\" & ModuleName & ".bas"
      If OverwriteExisting = True Then
          If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
              Err.Clear
              Kill FName
              If Err.Number <> 0 Then
                  CopyModule = False
                  Exit Function
              End If
          End If
          With ToVBProject.VBComponents
              .Remove .Item(ModuleName)
          End With
      Else
          Err.Clear
          Set VBComp = ToVBProject.VBComponents(ModuleName)
          If Err.Number <> 0 Then
              If Err.Number = 9 Then
                  ' module doesn't exist. ignore error.
              Else
                  ' other error. get out with return value of False
                  CopyModule = False
                  Exit Function
              End If
          End If
      End If
      FromVBProject.VBComponents(ModuleName).Export Filename:=FName
      SlashPos = InStrRev(FName, "\")
      ExtPos = InStrRev(FName, ".")
      CompName = Mid(FName, SlashPos + 1, ExtPos - SlashPos - 1)
      Set VBComp = Nothing
      Set VBComp = ToVBProject.VBComponents(CompName)
      If VBComp Is Nothing Then
          ToVBProject.VBComponents.Import Filename:=FName
      Else
          Set TempVBComp = ToVBProject.VBComponents.Import(FName)
          ' TempVBComp is source module
          With VBComp.CodeModule
              .DeleteLines 1, .CountOfLines
              S = TempVBComp.CodeModule.Lines(1, TempVBComp.CodeModule.CountOfLines)
              .InsertLines 1, S
          End With
          On Error GoTo 0
          ToVBProject.VBComponents.Remove TempVBComp
      End If
      Kill FName
      CopyModule = True
End Function
[/vba]

Автор - KuklP
Дата добавления - 21.02.2011 в 12:42
Alex_ST Дата: Понедельник, 21.02.2011, 12:45 | Сообщение № 14
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
А может для модулей листов не импорт делать (ты вроде говоришь, что тогда из модулей листов модули класса получаются?), а тупо по одной в цикле текстом переписывать строки начиная с 1 до CodeModule.CountOfLines?
Хотя тогда даже если мы ОЛЕ-объекты листа и сможем скопировать на новый лист, они, наверное, окажутся связанными со старым модулем листа...



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеА может для модулей листов не импорт делать (ты вроде говоришь, что тогда из модулей листов модули класса получаются?), а тупо по одной в цикле текстом переписывать строки начиная с 1 до CodeModule.CountOfLines?
Хотя тогда даже если мы ОЛЕ-объекты листа и сможем скопировать на новый лист, они, наверное, окажутся связанными со старым модулем листа...

Автор - Alex_ST
Дата добавления - 21.02.2011 в 12:45
Alex_ST Дата: Понедельник, 21.02.2011, 12:57 | Сообщение № 15
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Ну, ты скорописец... Пока я ответ вводил, ты уже новый макрос накатал!
Спасибо. Буду разбираться.



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеНу, ты скорописец... Пока я ответ вводил, ты уже новый макрос накатал!
Спасибо. Буду разбираться.

Автор - Alex_ST
Дата добавления - 21.02.2011 в 12:57
KuklP Дата: Понедельник, 21.02.2011, 13:17 | Сообщение № 16
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
А кнопки все равно будут ссылаться на старую книгу.


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728


Сообщение отредактировал KuklP - Понедельник, 21.02.2011, 13:20
 
Ответить
СообщениеА кнопки все равно будут ссылаться на старую книгу.

Автор - KuklP
Дата добавления - 21.02.2011 в 13:17
Alex_ST Дата: Понедельник, 21.02.2011, 15:26 | Сообщение № 17
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Серёга, я твой код как всегда малость "полирнул" для ясности и сделал так, чтобы его можно было разместить в Personal.xls Честно признаюсь: в работе с VBProject и VBComponents я плаваю по поверхности, поэтому там почти ничего не менял.
(текст превысил допустимую длину, поэтому попробую приложить в следующем посте)

Ещё недоработку обнаружил: в давно использующихся книгах страницы удаляют/добавляют, переставляют...
Поэтому ПРОГРАММНЫЕ номера страниц идут не по порядку и с пропусками.
А в новой книге новые страницы создаются в цикле For Each по порядку расположения их ярлыков листов в старой, т.е. по индексу. И после создания автоматом получают очередное программное имя. Т.е. если самым левым в старой книге был лист с программным номером 9, то в новой книге копия этого листа будет иметь и индекс и программный номер 1, код на него не экспортируется, а для кода старого листа 9 в новой книге будет создан модуль класса Лист9. Я у Климова на msoffice.nm.ru посмотрел как изменять кодовые имена листов... Не могу никак присобачить к твоему коду. sad
Хорошо бы, наверное, перед началом обработки перенумеровать программные имена (индексы) страниц в старой книге, а уж потом начинать копировать/экспортировать.




С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Понедельник, 21.02.2011, 16:33
 
Ответить
СообщениеСерёга, я твой код как всегда малость "полирнул" для ясности и сделал так, чтобы его можно было разместить в Personal.xls Честно признаюсь: в работе с VBProject и VBComponents я плаваю по поверхности, поэтому там почти ничего не менял.
(текст превысил допустимую длину, поэтому попробую приложить в следующем посте)

Ещё недоработку обнаружил: в давно использующихся книгах страницы удаляют/добавляют, переставляют...
Поэтому ПРОГРАММНЫЕ номера страниц идут не по порядку и с пропусками.
А в новой книге новые страницы создаются в цикле For Each по порядку расположения их ярлыков листов в старой, т.е. по индексу. И после создания автоматом получают очередное программное имя. Т.е. если самым левым в старой книге был лист с программным номером 9, то в новой книге копия этого листа будет иметь и индекс и программный номер 1, код на него не экспортируется, а для кода старого листа 9 в новой книге будет создан модуль класса Лист9. Я у Климова на msoffice.nm.ru посмотрел как изменять кодовые имена листов... Не могу никак присобачить к твоему коду. sad
Хорошо бы, наверное, перед началом обработки перенумеровать программные имена (индексы) страниц в старой книге, а уж потом начинать копировать/экспортировать.


Автор - Alex_ST
Дата добавления - 21.02.2011 в 15:26
Alex_ST Дата: Понедельник, 21.02.2011, 15:29 | Сообщение № 18
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
[vba]
Код
Option Explicit
Option Base 1

Sub ReduceSize()
      Dim LastRow As Long
      Dim LastColumn As Integer
      Dim arrRowHeight() As Single
      Dim arrColumnWidth() As Single
      Dim newWbk As Workbook
      Dim oldWbName As String
      Dim newWbName As String
      Dim WbPath As String
      Dim ShtName As String
      Dim Sht As Worksheet
      Dim n As Integer
      Dim i As Integer
      oldWbName = ActiveWorkbook.Name   ' запомним имя старой книги
      WbPath = ActiveWorkbook.Path   ' запомним путь к старой книге
      Set newWbk = Workbooks.Add   ' создадим новую книгу (она сразу станет ActiveWorkbook)
      ActiveWorkbook.SaveAs WbPath & "\" & "(NEW) " & oldWbName   'сохраним новую книгу рядом со старой с префиксом к имени "(NEW) "
      newWbName = ActiveWorkbook.Name   ' запомним имя новой книги
      i = 1   ' начинаем с первой страницы новой книги
      For Each Sht In Workbooks(oldWbName).Sheets   ' цикл по всем листам старой книги
         Sht.Activate
         With ActiveSheet
            ShtName = .Name
            LastRow = .Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row   ' последняя строка на листе, содержащая хоть какие-нибудь значения
            LastColumn = .Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column   ' последний столбец на листе, содержащий хоть какие-нибудь значения
            ReDim arrRowHeight(LastRow)
            ReDim arrColumnWidth(LastColumn)
            For n = 1 To LastRow   ' запомним высоты строк в массив
               arrRowHeight(n) = .Rows(n).RowHeight
            Next n
            For n = 1 To LastColumn   ' запомним ширины столбцов в массив
               arrColumnWidth(n) = .Columns(n).ColumnWidth
            Next n
            Application.CutCopyMode = False
            Range(.Cells(1, 1), .Cells(LastRow, LastColumn)).Copy   ' копируем только диапазон, содержащий данные
         End With
         With Workbooks(newWbName)
            If .Sheets.Count < i Then .Sheets.Add after:=.Sheets(.Sheets.Count)
            .Sheets(i).Name = ShtName
            .Sheets(i).Paste   ' копируем на страницу новой книги диапазон, содержащий данные
            Application.CutCopyMode = False
            For n = 1 To LastRow   ' восстановим высоты строк
               .Sheets(i).Rows(n).RowHeight = arrRowHeight(n)
            Next n
            For n = 1 To LastColumn   ' восстановим ширины столбцов
               .Sheets(i).Columns(n).ColumnWidth = arrColumnWidth(n)
            Next n
         End With
         i = i + 1   ' продолжим на следующей странице новой книги
      Next
      Application.DisplayAlerts = False
      Call ExportAllStdModules(newWbk, Workbooks(oldWbName))   ' скопировать все компоненты VBA в новую книгу
      Workbooks(newWbName).Save
      Workbooks(oldWbName).Close savechanges:=True
      Application.DisplayAlerts = True
End Sub
[/vba]

продолжение следует



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Понедельник, 21.02.2011, 15:30
 
Ответить
Сообщение[vba]
Код
Option Explicit
Option Base 1

Sub ReduceSize()
      Dim LastRow As Long
      Dim LastColumn As Integer
      Dim arrRowHeight() As Single
      Dim arrColumnWidth() As Single
      Dim newWbk As Workbook
      Dim oldWbName As String
      Dim newWbName As String
      Dim WbPath As String
      Dim ShtName As String
      Dim Sht As Worksheet
      Dim n As Integer
      Dim i As Integer
      oldWbName = ActiveWorkbook.Name   ' запомним имя старой книги
      WbPath = ActiveWorkbook.Path   ' запомним путь к старой книге
      Set newWbk = Workbooks.Add   ' создадим новую книгу (она сразу станет ActiveWorkbook)
      ActiveWorkbook.SaveAs WbPath & "\" & "(NEW) " & oldWbName   'сохраним новую книгу рядом со старой с префиксом к имени "(NEW) "
      newWbName = ActiveWorkbook.Name   ' запомним имя новой книги
      i = 1   ' начинаем с первой страницы новой книги
      For Each Sht In Workbooks(oldWbName).Sheets   ' цикл по всем листам старой книги
         Sht.Activate
         With ActiveSheet
            ShtName = .Name
            LastRow = .Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row   ' последняя строка на листе, содержащая хоть какие-нибудь значения
            LastColumn = .Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column   ' последний столбец на листе, содержащий хоть какие-нибудь значения
            ReDim arrRowHeight(LastRow)
            ReDim arrColumnWidth(LastColumn)
            For n = 1 To LastRow   ' запомним высоты строк в массив
               arrRowHeight(n) = .Rows(n).RowHeight
            Next n
            For n = 1 To LastColumn   ' запомним ширины столбцов в массив
               arrColumnWidth(n) = .Columns(n).ColumnWidth
            Next n
            Application.CutCopyMode = False
            Range(.Cells(1, 1), .Cells(LastRow, LastColumn)).Copy   ' копируем только диапазон, содержащий данные
         End With
         With Workbooks(newWbName)
            If .Sheets.Count < i Then .Sheets.Add after:=.Sheets(.Sheets.Count)
            .Sheets(i).Name = ShtName
            .Sheets(i).Paste   ' копируем на страницу новой книги диапазон, содержащий данные
            Application.CutCopyMode = False
            For n = 1 To LastRow   ' восстановим высоты строк
               .Sheets(i).Rows(n).RowHeight = arrRowHeight(n)
            Next n
            For n = 1 To LastColumn   ' восстановим ширины столбцов
               .Sheets(i).Columns(n).ColumnWidth = arrColumnWidth(n)
            Next n
         End With
         i = i + 1   ' продолжим на следующей странице новой книги
      Next
      Application.DisplayAlerts = False
      Call ExportAllStdModules(newWbk, Workbooks(oldWbName))   ' скопировать все компоненты VBA в новую книгу
      Workbooks(newWbName).Save
      Workbooks(oldWbName).Close savechanges:=True
      Application.DisplayAlerts = True
End Sub
[/vba]

продолжение следует

Автор - Alex_ST
Дата добавления - 21.02.2011 в 15:29
Alex_ST Дата: Понедельник, 21.02.2011, 15:29 | Сообщение № 19
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
продолжение:
[vba]
Код
Private Sub ExportAllStdModules(newWbk As Workbook, oldWbk As Workbook)   ' скопировать все компоненты VBA в новую книгу
      Dim iTempPath As String, iModuleName As String
      Dim iVBComponent As Object
      Dim a As Boolean
      With Application
         .ScreenUpdating = False
         iTempPath = .DefaultFilePath & .PathSeparator
         With newWbk.VBProject.VBComponents
            For Each iVBComponent In oldWbk.VBProject.VBComponents
               iModuleName$ = iTempPath$ & iVBComponent.Name
               a = CopyModule(iVBComponent.Name, _
                    oldWbk.VBProject, _
                    newWbk.VBProject, True)
            Next
         End With
         .ScreenUpdating = True
      End With
End Sub

Function CopyModule(ModuleName As String, _
                       FromVBProject, _
                       ToVBProject, _
                       OverwriteExisting As Boolean) As Boolean
      Dim VBComp As Object   'As VBIDE.VBComponent
      Dim FName$, CompName$, S$
      Dim SlashPos&, ExtPos&
      Dim TempVBComp      'As VBIDE.VBComponent
      Dim vbext_pp_locked As Boolean
      On Error Resume Next
      Set VBComp = FromVBProject.VBComponents(ModuleName)
      If Err.Number <> 0 Then
         CopyModule = False
         Exit Function
      End If
      FName = Environ("Temp") & "\" & ModuleName & ".bas"
      If OverwriteExisting = True Then
         If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
            Err.Clear
            Kill FName
            If Err.Number <> 0 Then
               CopyModule = False
               Exit Function
            End If
         End If
         With ToVBProject.VBComponents
            .Remove .Item(ModuleName)
         End With
      Else
         Err.Clear
         Set VBComp = ToVBProject.VBComponents(ModuleName)
         If Err.Number <> 0 Then
            If Err.Number = 9 Then
               ' module doesn't exist. ignore error.
            Else
               ' other error. get out with return value of False
               CopyModule = False
               Exit Function
            End If
         End If
      End If
      FromVBProject.VBComponents(ModuleName).Export FileName:=FName
      SlashPos = InStrRev(FName, "\")
      ExtPos = InStrRev(FName, ".")
      CompName = Mid(FName, SlashPos + 1, ExtPos - SlashPos - 1)
      Set VBComp = Nothing
      Set VBComp = ToVBProject.VBComponents(CompName)
      If VBComp Is Nothing Then
         ToVBProject.VBComponents.Import FileName:=FName
      Else
         Set TempVBComp = ToVBProject.VBComponents.Import(FName)
         ' TempVBComp is source module
         With VBComp.CodeModule
            .DeleteLines 1, .CountOfLines
            S = TempVBComp.CodeModule.Lines(1, TempVBComp.CodeModule.CountOfLines)
            .InsertLines 1, S
         End With
         On Error GoTo 0
         ToVBProject.VBComponents.Remove TempVBComp
      End If
      Kill FName
      CopyModule = True
End Function
[/vba]



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Понедельник, 21.02.2011, 15:30
 
Ответить
Сообщениепродолжение:
[vba]
Код
Private Sub ExportAllStdModules(newWbk As Workbook, oldWbk As Workbook)   ' скопировать все компоненты VBA в новую книгу
      Dim iTempPath As String, iModuleName As String
      Dim iVBComponent As Object
      Dim a As Boolean
      With Application
         .ScreenUpdating = False
         iTempPath = .DefaultFilePath & .PathSeparator
         With newWbk.VBProject.VBComponents
            For Each iVBComponent In oldWbk.VBProject.VBComponents
               iModuleName$ = iTempPath$ & iVBComponent.Name
               a = CopyModule(iVBComponent.Name, _
                    oldWbk.VBProject, _
                    newWbk.VBProject, True)
            Next
         End With
         .ScreenUpdating = True
      End With
End Sub

Function CopyModule(ModuleName As String, _
                       FromVBProject, _
                       ToVBProject, _
                       OverwriteExisting As Boolean) As Boolean
      Dim VBComp As Object   'As VBIDE.VBComponent
      Dim FName$, CompName$, S$
      Dim SlashPos&, ExtPos&
      Dim TempVBComp      'As VBIDE.VBComponent
      Dim vbext_pp_locked As Boolean
      On Error Resume Next
      Set VBComp = FromVBProject.VBComponents(ModuleName)
      If Err.Number <> 0 Then
         CopyModule = False
         Exit Function
      End If
      FName = Environ("Temp") & "\" & ModuleName & ".bas"
      If OverwriteExisting = True Then
         If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
            Err.Clear
            Kill FName
            If Err.Number <> 0 Then
               CopyModule = False
               Exit Function
            End If
         End If
         With ToVBProject.VBComponents
            .Remove .Item(ModuleName)
         End With
      Else
         Err.Clear
         Set VBComp = ToVBProject.VBComponents(ModuleName)
         If Err.Number <> 0 Then
            If Err.Number = 9 Then
               ' module doesn't exist. ignore error.
            Else
               ' other error. get out with return value of False
               CopyModule = False
               Exit Function
            End If
         End If
      End If
      FromVBProject.VBComponents(ModuleName).Export FileName:=FName
      SlashPos = InStrRev(FName, "\")
      ExtPos = InStrRev(FName, ".")
      CompName = Mid(FName, SlashPos + 1, ExtPos - SlashPos - 1)
      Set VBComp = Nothing
      Set VBComp = ToVBProject.VBComponents(CompName)
      If VBComp Is Nothing Then
         ToVBProject.VBComponents.Import FileName:=FName
      Else
         Set TempVBComp = ToVBProject.VBComponents.Import(FName)
         ' TempVBComp is source module
         With VBComp.CodeModule
            .DeleteLines 1, .CountOfLines
            S = TempVBComp.CodeModule.Lines(1, TempVBComp.CodeModule.CountOfLines)
            .InsertLines 1, S
         End With
         On Error GoTo 0
         ToVBProject.VBComponents.Remove TempVBComp
      End If
      Kill FName
      CopyModule = True
End Function
[/vba]

Автор - Alex_ST
Дата добавления - 21.02.2011 в 15:29
KuklP Дата: Понедельник, 21.02.2011, 17:10 | Сообщение № 20
Группа: Проверенные
Ранг: Старожил
Сообщений: 2369
Репутация: 486 ±
Замечаний: 0% ±

2003-2010
[vba]
Код
Public Sub www()
Dim Sh As Object, iCodeName$
For Each Sh In Sheets
iCodeName = Sh.CodeName
Application.VBE.ActiveVBProject.VBComponents(iCodeName).Name = Sh.Name
Next
End Sub
[/vba]


Ну с НДС и мы чего-то стoим! kuklp60@gmail.com
WM Z206653985942, R334086032478, U238399322728


Сообщение отредактировал KuklP - Понедельник, 21.02.2011, 17:37
 
Ответить
Сообщение[vba]
Код
Public Sub www()
Dim Sh As Object, iCodeName$
For Each Sh In Sheets
iCodeName = Sh.CodeName
Application.VBE.ActiveVBProject.VBComponents(iCodeName).Name = Sh.Name
Next
End Sub
[/vba]

Автор - KuklP
Дата добавления - 21.02.2011 в 17:10
Мир MS Excel » Вопросы и решения » Готовые решения » Файл распух до нелогичных размеров. (Один из способов уменьшить размер файла.)
  • Страница 1 из 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • »
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!