Макрос для Excel: если столбец B имеет «X», скопируйте всю строку и вставьте в рабочую таблицу «Column B» - PullRequest
1 голос
/ 02 марта 2012

У меня ограниченный опыт написания макросов, и я хочу обновить текущую электронную таблицу, используемую на работе. В настоящее время мы копируем весь мастер-лист и вставляем его в другие листы перед сортировкой по «X» в определенных столбцах, чтобы удалить другие строки на мастер-листе.

Что я хочу сделать, так это выполнить поиск в Главном листе, и если в столбце B есть «X», скопируйте всю строку и вставьте ее в рабочий лист с именем «Столбец B». Затем, после завершения и вставки столбца B, он будет смотреть на столбец D. Если в столбце D есть «X», он скопирует всю строку и вставит ее на вкладку листа с именем «Столбец D».

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 03 марта 2012

Подход

Я должен был включить это в первую версию моего ответа.

Мое решение зависит от автофильтра.Сначала я предлагаю игровое решение, демонстрирующее этот подход:

  1. делая строки, не содержащие X в столбце B, невидимыми
  2. делая строки, не содержащие X в столбце D, невидимыми
  3. очистка автофильтра

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

Если этот подходне подходит, я предлагаю второе решение, которое включает в себя копирование видимых строк, оставленных каждым фильтром, в другие таблицы.

Введение

Вы говорите «у меня ограниченный опыт написания макросов», что, как я понимаю, означает, что у вас есть некоторый опыт.Надеюсь, у меня правильный уровень объяснений.При необходимости возвращайтесь с вопросами.

Я предполагаю, что ваша рабочая книга находится на сервере.Я предполагаю, что у кого-то есть права на запись для обновления главной рабочей таблицы, в то время как другие открывают копии только для чтения, чтобы они могли просматривать интересующие их подмножества.Если мои предположения верны, возьмите копию рабочей тетради, с которой вы сможете поиграть.Не беспокойтесь о том, что другие обновят основную версию рабочей книги, мы завершим окончательную версию кода из вашей игровой версии, когда закончим.

Шаг 1

Скопируйте первый блок кода в модуль в версии воспроизведения.Около дна вы найдете Const WShtMastName As String = "SubSheetSrc".Замените SubSheetSrc на имя вашего основного рабочего листа.

Примечание. Макросы в этом блоке имеют имена CtrlCreateSubSheetB и CreateSubSheetB, поскольку они являются играющими версиями.Реальные версии имеют имена CtrlCreateSubSheet и CreateSubSheet.

Запуск макроса CtrlCreateSubSheetB.Вы увидите мастер-лист, но только те строки с «X» в столбце B. Нажмите на окно сообщения. Вы увидите мастер-лист, но только те строки с «X» в столбце D. Нажмите на окно сообщения ифильтр исчезнет.Переключитесь на VB Editor, если вы еще не там.В «Немедленном окне» (нажмите Ctrl + G, если его не видно), и вы увидите что-то вроде:

Rows with X in column 2: $A$1:$G$2,$A$4:$G$5,$A$8:$G$9,$A$11:$G$12,$A$14:$G$14, ...
Rows with X in column 4: $A$1:$G$1,$A$3:$G$3,$A$5:$G$5,$A$7:$G$7,$A$10:$G$10, ...

Теперь работайте с макросами CtrlCreateSubSheetB и CreateSubSheetB.Вы должны понимать, как эти макросы создали эффекты, которые вы видели.При необходимости используйте VB Help, Debugger и F8, чтобы отключить макросы, чтобы определить, что делает каждый оператор.Я полагаю, что предоставил вам достаточно информации, но при необходимости вернусь с вопросами.

' Option Explicit means I have to declare every variable.  It stops
' spelling mistakes being taken as declarations of new variables.
Option Explicit

' Specify a subroutine with two parameters
Sub CreateSubSheetB(ByVal WShtSrcName As String, ByVal ColSrc As Long)

  ' This macro applies an AutoFilter based on column ColSrc
  ' to the worksheet named WShtSrcName

  Dim RngVis As Range

  With Sheets(WShtSrcName)
    If .AutoFilterMode Then
      ' AutoFilter is on.  Cancel current selection before applying
      ' new one because criteria are additive.
      .AutoFilterMode = False
    End If

    ' Make all rows which do not have an X in column ColSrc invisible
    .Cells.AutoFilter Field:=ColSrc, Criteria1:="X"

    ' Set the range RngVis to the union of all visible rows
    Set RngVis = .AutoFilter.Range.SpecialCells(xlCellTypeVisible)

  End With

  ' Output a string to the Immediate window.
  Debug.Print "Rows with X in column " & ColSrc & ": " & RngVis.Address

End Sub

' A macro to call CreateSubSheetB for different columns
Sub CtrlCreateSubSheetB()

  Const WShtMastName As String = "SubSheetSrc"

  Dim WShtOrigName As String

  ' Save the active worksheet
  WShtOrigName = ActiveSheet.Name

  ' Make the master sheet active if it is not already active so
  ' you can see the different filtered as they are created.
  If WShtOrigName <> WShtMastName Then
    Sheets(WShtMastName).Activate
  End If

  ' Call CreateSubSheet for column 2 (=B) then column 4 (=D)

  Call CreateSubSheetB(WShtMastName, 2)
  Call MsgBox("Click to continue", vbOKOnly)
  Call CreateSubSheetB(WShtMastName, 4)
  Call MsgBox("Click to continue", vbOKOnly)
  With Sheets(WShtMastName)
    If .AutoFilterMode Then
      .AutoFilterMode = False
    End If
  End With

  ' Restore the original worksheet if necessary
  If WShtOrigName <> WShtMastName Then
    Sheets(WShtOrigName).Activate
  End If

End Sub

Шаг 2

Если мои предположения о том, как вы используете книгу, вернывам может не понадобиться намного больше.Если Джон и Мэри откроют открытую для чтения копию главной рабочей книги, тогда Джон сможет использовать фильтр B, а Мэри - фильтр D.Если это звучит интересно, посмотрите на мой ответ скопировать данные строки с одного листа на один или несколько листов на основе значений в других ячейках .

Шаг 3

Если вам не нравится идея использования фильтров и вы все еще хотите создавать копии данных B и данных D, вам понадобится приведенный ниже код.

Макросы в этом блоке называютсяCtrlCreateSubSheet и CreateSubSheet, но не сильно отличаются от версий B, указанных выше.

В CtrlCreateSubSheet вам необходимо заменить «SubSheetSrc», «SubSheetB» и «SubSheetD» на ваши имена для этих рабочих листов.,Добавьте дополнительные вызовы CreateSubSheet для любых дополнительных контрольных столбцов.

Примечание: эти версии удаляют исходное содержимое листов назначения, хотя это не то, что вы просили.Я удалил исходное содержимое, потому что (1) то, что вы добавляете новые строки, является более сложным и (2) я не верю, что вы правы.Если какое-то значение имеет то, что вы просили, вернитесь, и я обновлю код.

Option Explicit
Sub CtrlCreateSubSheet()

  Const WShtMastName As String = "SubSheetSrc"

  ' Call CreateSubSheet for column 2 (=B) then column 4 (=D)

  Application.ScreenUpdating = False

  Call CreateSubSheet(WShtMastName, 2, "SubSheetB")
  Call CreateSubSheet(WShtMastName, 4, "SubSheetD")
  With Sheets(WShtMastName)
    If .AutoFilterMode Then
      .AutoFilterMode = False
    End If
  End With

  Application.ScreenUpdating = True

End Sub
Sub CreateSubSheet(ByVal WShtSrcName As String, ByVal ColSrc As Long, _
                    ByVal WShtDestName As String)

  ' This macro applies an AutoFilter based on column ColSrc to the worksheet
  ' named WShtSrcName. It then copies the visible rows to the worksheet
  ' named WShtDestName

  Dim RngVis As Range
  Dim WShtOrigName As String

  With Sheets(WShtSrcName)
    If .AutoFilterMode Then
      ' AutoFilter is on.  Cancel current selection before applying
      ' new one because criteria are additive.
      .AutoFilterMode = False
    End If

    ' Make all rows which do not have an X in column ColSrc invisible
    .Cells.AutoFilter Field:=ColSrc, Criteria1:="X"

    ' Set the range RngVis to the union of all visible cells
    Set RngVis = .AutoFilter.Range.SpecialCells(xlCellTypeVisible)

  End With

  If RngVis Is Nothing Then
    ' There are no visible rows.  Since the header row will be visible even if
    ' there are no Xs in column ColSrc, I do not believe this block can
    ' be reached but better to be safe than sorry.
    Call MsgBox("There are no rows with an X in column " & ColSrc, vbOKOnly)
    Exit Sub
  End If

  ' Copy visible rows to worksheet named WShtDestName

  With Sheets(WShtDestName)

    ' First clear current contents of worksheet named WShtDestName
    .Cells.EntireRow.Delete

    ' Copy column widths to destination sheets
    Sheets(WShtSrcName).Rows(1).Copy
    .Rows(1).PasteSpecial Paste:=xlPasteColumnWidths

    ' I do not recall using SpecialPaste column widths before and it did not
    ' work as I expected.  Hunting around the internet I found a link to a   
    ' Microsoft page which gives a workaround.  This workaround worked in
    ' that it copied the column widths but it left row 1 selected.  I have
    ' added the following code partly because I like using FreezePanes and
    ' partly to unselect row 1.
    WShtOrigName = ActiveSheet.Name
    If WShtOrigName <> WShtDestName Then
      .Activate
    End If
    .Range("A2").Select
    ActiveWindow.FreezePanes = True
    If WShtOrigName <> WShtDestName Then
      Sheets(WShtOrigName).Activate
    End If

    ' Copy all the visible rows in the Master sheet to the destination sheet. 
    RngVis.Copy Destination:=.Range("A1")

  End With

End Sub

Шаг 4

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

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

Вам нужно будет научить того, кто отвечает за обновление мастер-версии, запускать макросы при завершении значительного обновления. Вы можете использовать сочетание клавиш или добавить макрос на панель инструментов, чтобы упростить использование макроса.

Резюме

Надеюсь, все это имеет смысл. Задавайте вопросы, если это необходимо.

0 голосов
/ 26 июня 2013

Проще:

Sub Columns()
    If WorkSheets("Sheet1").Range("B1") = x Then
        WorkSheets("Column B").Range("B2") = WorkSheets("Sheet1").Range("B2:B" & Rows.Count).End(xlup).Row
    End if
    If WorkSheets("Sheet1").Range("D1") = x Then
        WorkSheets("Column D").Range("D2") = WorkSheets("Sheet1").Range("D2:D" & Rows.Count).End(xlup).Row
    End if
End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...