Ни для кого не секрет, что Excel позволяет выделять только видимые строки. Например, если некоторые из них скрыты или к ним применен фильтр.
если кто-то не знает, как это сделать: выделяем диапазон -
Alt +; (для английской раскладки);Alt +ж (для русской). Подробнее можно почитать в этой статье
Если после выделения только видимых ячеек их скопировать, то скопируются они как положено. Но при попытке вставить скопированное в отфильтрованный диапазон(либо содержащий скрытые строки) - результат вставки будет не совсем такой, как ожидалось. Данные будут вставлены даже в скрытые строки. Либо может появиться ошибка "Данная команда не применима к несвязанным диапазонам".
Решить стандартными функциями такую проблему нельзя, поэтому на помощь приходят "макросы"(коды, написанные на встроенном языке программирования Visual Basic for Application).
Для решения проблемы нам по сути надо будет и копировать и вставлять ячейки кодом. Т.е. мы не будем использовать привычное копирование. Мы заменим его своей собственной процедурой копирования - макрос "My_Copy". А вставка будет макросом "My_Paste".
Итак, коды копирования и вставки:
Option Explicit Dim rCopyRange As Range 'Этим макросом копируем данные Sub My_Copy() If Selection.Count > 1 Then Set rCopyRange = Selection.SpecialCells(xlVisible) Else: Set rCopyRange = ActiveCell End If End Sub 'Этим макросом вставляем данные, начиная с выделенной ячейки Sub My_Paste() If rCopyRange Is Nothing Then Exit Sub If rCopyRange.Areas.Count > 1 Then MsgBox "Вставляемый диапазон не должен содержать более одной области!", vbCritical, "Неверный диапазон": Exit Sub Dim rCell As Range, li As Long, le As Long, lCount As Long, iCol As Integer, iCalculation As Integer Application.ScreenUpdating = False iCalculation = Application.Calculation: Application.Calculation = -4135 For iCol = 1 To rCopyRange.Columns.Count li = 0: lCount = 0: le = iCol - 1 For Each rCell In rCopyRange.Columns(iCol).Cells Do If ActiveCell.Offset(li, le).EntireColumn.Hidden = False And _ ActiveCell.Offset(li, le).EntireRow.Hidden = False Then rCell.Copy ActiveCell.Offset(li, le) lCount = lCount + 1 End If li = li + 1 Loop While lCount >= rCell.Row - rCopyRange.Cells(1).Row Next rCell Next iCol Application.ScreenUpdating = True: Application.Calculation = iCalculation End Sub |
Чтобы скопировать диапазон, надо выделить его и вызвать процедуру "My_Copy". Затем выделяем первую ячейку для вставки и вызываем код "My_Paste".
Но для большего удобства использования лучше назначить выполнение этих двух процедур("My_Copy" и "My_Paste") на горячие клавиши(в приведенных ниже кодах это делается автоматически при открытии книги с кодом). Для этого приведенные ниже коды необходимо просто скопировать в модуль ЭтаКнига(ThisWorkbook):
Option Explicit 'Отменяем назначение горячих клавиш перед закрытием книги Private Sub Workbook_BeforeClose(Cancel As Boolean) Application.OnKey "^q": Application.OnKey "^w" End Sub 'Назначаем горячие клавиши при открытии книги Private Sub Workbook_Open() Application.OnKey "^q", "My_Copy": Application.OnKey "^w", "My_Paste" End Sub |
Тогда при каждом открытии книги с кодом сочетание клавиш
Если необходимо
rCell.Copy ActiveCell.Offset(li, le) |
на такую:
ActiveCell.Offset(li, le) = rCell.Value |
Примечание: в коде выше копируется весь диапазон, даже если он содержит скрытые или отфильтрованные строки.
Tips_Macro_CopyPasteInHiddenRows.xls (46,5 КиБ, 15 549 скачиваний)
По многочисленным просьбам доработал код. Данным кодом возможно копировать любые диапазоны: со скрытыми строками, скрытыми столбцами и вставлять скопированные ячейки также в любые диапазоны: со скрытыми строками, скрытыми столбцами. Работает совершенно так же, как и предыдущий: нажатием клавиш
Если в копируемом диапазоне присутствуют формулы, то во избежание смещения ссылок можно копировать только значения ячеек - т.е. при вставке значений будут вставлены не формулы, а результат их вычисления. Или если необходимо сохранить форматы ячеек, в которые происходит вставка - будут скопированы и вставлены только значения ячеек. Для этого надо заменить строку в коде(в файле ниже):
rCell.Copy rResCell.Offset(lr, lc) |
на такую:
rResCell.Offset(lr, lc) = rCell.Value |
В файле ниже обе эти строки присутствуют, надо лишь оставить ту, которая больше подходит под выполняемые задачи.
Tips_Macro_CopyPasteInHiddenCells.xls (54,5 КиБ, 14 526 скачиваний)
Так же см.:
Excel удаляет вместо отфильтрованных строк - все?! Как избежать
[MulTEx]Копировать только видимые ячейки
Дмитрий, здравствуйте!
У меня почему-то не работают ваши файлы.
Приведу пример на последнем файле:
Открываю его в Excel 2013; разрешаю редактирование-вылезает ошибка Run-time error '1004':
Method 'OnKey' of object'_Application' failed
Когда нажимаю debug вылезает окошко макроса и там подсвечена желтым часть строки:
Application.OnKey "^q", "My_Copy"
А если пробую нажимать в таблице ctrl+q, то вылезает окошко форматирования
Подскажите, пожалуйста, как это исправить.
Дмитрий, когда скачиваете файл с интернета - он открывается в защищенном режиме, о чем у Вас появляется предупреждение. Нельзя обратиться к свойствам листов и книг, если книга открыта в защищенном режиме. А именно так по умолчанию открываются книги, скачанные откуда-то. Варианта по сути два:
1. При открытии файла разрешить редактирование и перезапустить книгу.
2. Добавить папку, в которую скачиваются вложения, в список доверенных(Файл -Параметры -Центр управления безопасностью -Параметры центра управления безопасностью -Надежные расположения).
Есть еще вариант: в настройках макросов разрешить запуск макросов с уведомлением. Тогда сначала будет появляться запрос на редактирование, а самым последним запрос на разрешение выполнения содержимого.
Дмитрий, спасибо большое!
После пересохранения книги и добавления надежного расположения все заработало=)
Дмитрий. Большое спасибо!
Готов донатить таким людям. Спасибо что вы есть
Еще раз здравствуйте!
А не подскажете, как копировать так, чтобы сохранялся формат и размеры ячеек в которые копируются данные?
В самом конце статьи написано какую строку на что заменить, чтобы форматы во вставляемых ячейках не изменялись и вставлялись только значения.
Прошу прощения за мою невнимательность, в памяти отложилось, что там было сказано только про формулы) Спасибо за ответ.
Все правильно отложилось, так и было. Я после Вашего комментария добавил, чтобы другие уже не искали.
Здравсвуйте. Подскажите как можно скорректировать Ваш код.
У Вас в коде активируется активная ячейка активного листа
Set rResCell = ActiveCell
А можно ли, что бы активировалась выбранная пользователем ячейка в другой книге. И с нее уже шла вставка.
Пытался написать макрос который бы активировал уже открытую книгу, но навыков в этом у меня не хватило.
Максим, в моем коде ничего не активируется :) Вы можете сочетанием клавиш(Ctrl+q) скопировать диапазон в одной книге, далее активировать нужную книгу, лист и ячейку в них и вставить, начиная с активной ячейки. Попробуйте.
Эти команды работают прекрасно ). Просто Ваш макрос я уже делаю под себя. И суть задачи была такова. Необходимо в рабочей книге заполнить диапазон значений, из другой книги, обе книги имеют скрытые ячейки. Для оптимизации работы из первой книги запускается макрос выбора необходимого файла, далее запускается макрос который выделяет в этом файле необходимый мне диапазон (диапазон всегда одинаковый), далее я применил ваш код для копирования и вставки. Но проблема в том что вставка идет в туже книгу из которой и копировалось. Жестко указать ячейку вставки в первой книге не получается, так как она всегда разная.
Максим, так если Вы переделали под себя - что хотите от меня? Я не могу угадать что и как Вы там изменили и куда чего вставлять собрались. Могу лишь посоветовать эту статью:Как обратиться к диапазону из VBA . Там написано как обратиться к диапазону другой книги/листа и т.п. Возможно, поможет.
Большое спасибо за ссылку. Ваш макрос уже облегчил мне работу, надеюсь что смогу до конца разобраться )
Дмитрий, добрый день
Подскажите, что я делаю не так?
Выходит ошибка " Вставляемый диапазон не должен содержать больше одной области"
Спасибо
Михаил, очевидно, не внимательно читали статью и копируете или вставляете диапазоны не при помощи указанных сочетаний(Ctrl+q и Ctrl+w), а стандартными средствами.
такая же ошибка при попытке вставить скопированный диапазон со скрытыми ячейками в новое место
пс. пользуюсь контроКУ +контролДаблЮ
Вопрос решился, почему то скопировался не весь скрипт
Георгий, ну вот давайте хотя бы так: Вы статью внимательно читали? Код используете, наверное, первый, тот что в статье, а не тот, что во втором файле? И диапазон при этом копируете тоже отфильтрованный. А первый код не работает с такими диапазонами, о чем и говорит. Если хотите копировать любые диапазоны(со скрытыми ячейками) и в такие же любые вставлять - ну прочтите статью и увидите, что в конце статьи я приложил еще файл, в котором реализован как раз более универсальный код. Сам код при этом в статье ОТСУТСТВУЕТ, он только в файле.
Дмитрий, Большое спасибо Вам за ваш макрос!
Дмитрий, спасибо вам огромное за данный макрос, он позволяет сэкономить уйму времени при работе =). Не могли бы вы подсказать, возможно ли данный макрос сделать так, что бы он вставлял не значениями, а связями (hyperlink).
Владислав, для оформления гиперссылками придется сильно потрудиться. При этом не думаю, что это лучшая мысль, т.к. у книг есть ограничения на общее кол-во гиперссылок. А из этого следует, что при больших объемах данных очень даже вероятен факт получения неработоспособного результирующего файла.
Мужик, ты просто чёртов ГЕНИЙ ! Рахмет огромный, у меня всё работает (копировал макрос из файла примера). Слегка доработал (у меня и источник копирования и файл вставки - оба защищены, я в начале каждого макроса вставил снятие пароля и в конце - опять на пароль).
Единственное, что не понимаю в твоём Коде - это вот это вот:
'получение отсортированных адресов диапазона
Function NoDups(rRng As Range) - для чего эта функция? И участвует ли она в макросах копирования и вставки? (насколько я понял - не участвует, но вдруг...)
daur251282, спасибо за отзыв. Функция NoDups нужна, чтобы отсортировать адреса скопированных ячеек в нужном порядке. Актуально, если выделение происходило через Ctrl или снизу вверх - в этом случае они по умолчанию могут располагаться в произвольном порядке и вставка пройдет неверно.
Да ты гениальный тип! Спасибо!
Дмитрий, спасибо за макрос, из всех найденных аналогичных он лудший.
Есть предложение для повышения удобства использования.
Зачем нужно копировать область средствами макроса? По Ctrl-C начиная с Excel 2007 уже копируются только отфильтрованные строки. Предлагаю их подхватить из буфера и вставлять по Ctrl-Q. Тогда может и обработка быстрее пойдет, на больших объемах-то думает долго.
А использование Ctrl-W неудобно, это стандартное сочетание винды для закрытия окон
ixet08, к сожалению у VBA нет нормального доступа к буферу обмена Excel. Поэтому приходится принудительно создавать новый объект, чтобы его обработать. При этом само по себе копирование не занимает больше времени, чем стандартное Ctrl+C. Тут проблема именно при вставке, т.к. идет определение скрытых или отображенных ячеек. И это не быстро. В своей надстройке MulTEx я значительно ускорил этот процесс, но там код уже совершенно иной.
Сочетания клавиш можно сменить на свои - где это сделать в статье показано(искать в модуле ЭтаКнига). Т.к. у всех разные предпочтения к гор.клавишам я специально отдельно привел код где это можно сделать.
Благодарю за ответ. Про проблему с доступом к буферу не знал.
Hotkeys уже настроил под себя