Измените пользовательскую форму для работы с несколькими листами

Я потратил большую часть последних нескольких недель на то, чтобы создать несколько пользовательских форм (не одна из моих сильных сторон). С моей предполагаемой пользовательской формой пользователь может выбрать любые значения, которые они хотят в электронной таблице (например, цены активов), а затем применить счетчик, это подражает увеличению / уменьшению% в цене этих активов и т. Д., А затем они могут наблюдать, как это влияет на различные аспекты бизнеса. Затем у них есть две кнопки, одна из которых позволяет сохранить настроенные значения, а другая – для сброса значений.

Пока у меня есть одна пользовательская форма, которая, как представляется, работает на разных листах, но выбранные диапазоны должны быть смежными, и один, с большой помощью здесь (см. Предыдущий вопрос от меня самого), который отлично работает для несмежных выборов, однако они должны быть включены тот же рабочий лист. Однако в идеале я хотел бы иметь возможность выбирать несколько несмежных диапазонов по нескольким листам и иметь возможность редактировать их. Я уверенно информирован о том, что переменные диапазона могут относиться только к диапазонам на конкретном листе, который, я полагаю, является местом, где я ошибаюсь.

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

Открытие Userform;

Public myRange As Range, myArea As Range Public myCopy As Variant Public i As Long, numAreas As Long Public pvar As Double Sub Button2_Click() Spinner.Show End Sub 

Пользовательская форма:

 Option Explicit 'on opening userform this sets the variables Private Sub UserForm_Activate() pvar = 1 Set myRange = Selection numAreas = myRange.Areas.Count If numAreas = 1 Then myCopy = myRange.Value Else ReDim myCopy(1 To numAreas) For i = 1 To numAreas myCopy(i) = myRange.Areas(i).Value Next i End If End Sub 'Useful Subs Sub RestoreVals(R As Range, V As Variant) Dim A As Range Dim i As Long, n As Long n = R.Areas.Count If n = 1 Then R.Value = V Else For i = 1 To n R.Areas(i).Value = V(i) Next i End If End Sub Sub Multiply(R As Range, p As Double) Dim c As Range For Each c In R.Cells c.Value = p * c.Value Next c End Sub 'Spin Up button Private Sub SpinButton1_SpinUp() Dim myRange As Range, myCopy As Variant Set myRange = Selection 'Reset Values so that pvar is * by the right values CopyVals myRange, myCopy Multiply myRange, (1 / pvar) 'Now * by pvar CopyVals myRange, myCopy pvar = pvar + UpBox.Value / 100 Multiply myRange, pvar End Sub ' Spin Down button Private Sub SpinButton1_SpinDown() Dim myRange As Range, myCopy As Variant Set myRange = Selection 'Reset Values so that pvar is * by the right values CopyVals myRange, myCopy Multiply myRange, (1 / pvar) 'Now * by pvar CopyVals myRange, myCopy pvar = pvar - DownBox.Value / 100 Multiply myRange, pvar End Sub 'Button to return to starting values Public Sub DefaultButton_Click() If numAreas = 1 Then myRange.Value = myCopy Else For i = 1 To numAreas myRange.Areas(i).Value = myCopy(i) Next i End If End Sub 'button to maintain adjusted values Private Sub CommandButton1_Click() UserForm3.Show End Sub 

В качестве доказательства концепции я создал следующую пользовательскую форму. В редакторе я устанавливаю ShowModal равным False. Это важно, поскольку позволяет пользователю переключаться на разные листы, пока отображается форма. Это выглядит так:

введите описание изображения здесь

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

 Option Explicit Dim valCopies As Collection Dim ranges As Collection Private Sub UserForm_Initialize() Dim r As Range tbChangeFactor.Value = "1.0" Set ranges = New Collection Set valCopies = New Collection For Each r In Selection.Areas ranges.Add r valCopies.Add r.Value Next r End Sub Private Sub btnChange_Click() Dim r As Range, c As Range, p As Double Application.ScreenUpdating = False p = tbChangeFactor.Value For Each r In ranges For Each c In r.Cells c = c * p Next c Next r Application.ScreenUpdating = True End Sub Private Sub btnRestore_Click() Dim i As Long, n As Long n = ranges.Count For i = 1 To n ranges(i).Value = valCopies(i) Next i End Sub Private Sub btnSelect_Click() Dim choice As Range, A As Range Dim home As Worksheet, ws As Worksheet Set valCopies = New Collection Set ranges = New Collection Set home = ActiveSheet For Each ws In Sheets ws.Select Set choice = Nothing On Error Resume Next 'when the user hits cancel Set choice = Application.InputBox("Select cells from " & ws.Name, "Change/Restore", Selection.Address, , , , , 8) On Error GoTo 0 If Not choice Is Nothing Then choice.Select 'for future reference For Each A In choice.Areas ranges.Add A valCopies.Add A.Value Next A End If Next ws home.Select End Sub 

Было бы легко изменить так, чтобы субтитры выбора выполнялись только по заранее заданному набору листов. Если я понимаю, что вы пытаетесь сделать, возможно, вы захотите запустить вспомогательный модуль восстановления в начале субстрата выбора, если вы хотите убедиться, что исходные (в отличие от измененных) значения сохраняются, когда пользователь запускает выбор не более одного раза. Код не был тщательно протестирован, но, похоже, работает. Слово предупреждения – области могут перекрываться, если пользователь делает странные вещи при выборе. Вышеприведенный код модифицирует любые ячейки, содержащиеся в таких перекрытиях 2 (или более) раза. Чтобы быть действительно безопасным, вы можете изменить код выбора, чтобы убедиться, что области не перекрываются. Одним из способов было бы управлять областями с помощью превосходной функции OwnUnion Чипа Пирсона: http://www.cpearson.com/Excel/BetterUnion.aspx

Каждое Window Excel отслеживает выбранные ячейки, поэтому вы можете прокручивать коллекцию Windows :

 Dim wdw As Window For Each wdw In Application.Windows Debug.Print wdw.Selection.Address(External:=True) Next wdw 

Но проблема с этим подходом заключается в том, что ваш код должен убедиться, что пользователь только открыл ожидаемые книги или проверил каждую книгу. Кроме того, что происходит, если пользователь имеет книгу в нескольких представлениях (кнопка «Новое окно» на вкладке «Вид»)?

  • Отключить / включить вкладку в Multitab на основе значения флажка-EXCEL
  • VBA Excel 2013: назначение значений массива из другой пользовательской формы
  • excel инициализирует «защищать / снимать защиту листа» с помощью пользовательской формы
  • Вызовите UserForm из модуля, чтобы отобразить всплывающие диаграммы и вернуться в одно и то же место в модуле
  • Excel VBA Userform IIf (IsDate) не сохраняет пробел
  • VBA - события прерывания в динамически создаваемом текстовом поле
  • Excel - VBA: передать переменную от Sub до Userform
  • Пользовательский календарь календаря Excel
  • не удалось заполнить combobox, используя .rowsource {vba excel}
  • Выровнять Userform с ячейками в Excel
  • Экземпляр контекстного меню Excel VBA
  • Давайте будем гением компьютера.