Навигация по листу - PullRequest
       6

Навигация по листу

0 голосов
/ 01 мая 2018

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

Это скриншот набора данных, в котором я хочу запустить calc:

img1

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

Пример кода для существующих расчетов:

ws.Range("B74").Select
Do Until ActiveCell.Offset(0, 1).Value = ""
ActiveCell.Offset(-23, 1).Formula = "=Round(((R[-2]C[0]+R[-4]C[0])/R[-14]C[0])*100,2)"
    If IsError(ActiveCell.Offset(-23, 1)) Then ActiveCell.Offset(-23, 1).Value = "0"
ActiveCell.Offset(0, 1).Select
Loop

1 Ответ

0 голосов
/ 02 мая 2018

В вашем случае я бы определил пользовательскую функцию (поместил макрос в стандартный модуль), а затем использовал эту функцию внутри листа в качестве формулы. Функция возвращает значение последней непустой ячейки, после чего вы можете выполнить расчет непосредственно на листе. Value2 используется для получения базового значения ячейки без учета форматов.

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

  • Цикл по диапазону (getLastValueWithLoop)
  • Использование .End (xlUp) (getLastValueWithEnd)
  • Запись значений диапазона в массив, а затем зацикливание массива (самое быстрое) (getLastValueWithArrayLoop)

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

Кстати: вы можете прорваться с помощью макросов и просто использовать обычную формулу (см. Скриншот).

Код:

' **
' Get the value of the last non empty cell in rng
' @param {Range} rng Range to look in, 1 column only
' @return {Variant} Returns the value of the last non empty cell
' or false if all cells are empty
' Example:
' Use following function inside a sheet:
' =getLastValueWithLoop(A2:A6)
Public Function getLastValueWithLoop(rng As Range) As Variant
    Dim i As Long

    ' Loop through range and check if cell is not empty
    ' Starts at the bottom and moves 1 cell up each time
    For i = rng.Cells.Count To 1 Step -1
        If rng(i).Value2 <> "" Then
            getLastValueWithLoop = rng(i).Value
            Exit Function
        End If
    Next

    ' if no value in range set to false
    getLastValueWithLoop = False
End Function

' **
' Get the value of the last non empty cell in rng
' @param {Range} rng Range to look in, 1 column only
' @return {Variant} Returns the value of the last non empty cell
' or false if all cells are empty
' Example:
' Use following function inside a sheet:
' =getLastValueWithEnd(A2:A6)
Public Function getLastValueWithEnd(rng As Range) As Variant
    Dim i As Long
    Dim lastCell As Range
    Dim lastNonEmptyCell As Range

    ' Set last cell in range
    Set lastCell = rng(rng.Cells.Count)

    ' Use .end(xlup) to get first non empty
    ' This is the same as using the keys CTRL + Up
    If lastCell <> "" Then
        ' Needs to check if last cell is empty first as else
        ' end(xlup) would move up even if the cell is non empty
        ' Set as last non empty cell if not empty
        getLastValueWithEnd = lastCell.Value2
        Exit Function
    Else
        ' Use end(xlup) to get the first non empty cell moving up from
        ' the last cell. Check if the cell found with end(xlup) is inside the range
        ' with .Intersect as end(xlup) can move outside the range provided
        ' If it is inside the range set last non empty cell
        If Not Application.Intersect(rng, lastCell.End(xlUp)) Is Nothing Then
            getLastValueWithEnd = lastCell.End(xlUp).Value2
            Exit Function
        End If
    End If

    ' if no value in range set to false
    getLastValueWithEnd = False
End Function

' **
' Get the value of the last non empty cell in rng
' @param {Range} rng Range to look in, 1 column only
' @return {Variant} Returns the value of the last non empty cell
' or false if all cells are empty
' Example:
' Use following function inside a sheet:
' =getLastValueWithArrayLoop(A2:A6)
Public Function getLastValueWithArrayLoop(rng As Range) As Variant
    Dim rngAsArray As Variant
    Dim i As Long

    ' Write the rng values into an array
    ' This produces a two dimensional array
    rngAsArray = rng.Value2

    ' Loop through the array, move from bottom up and
    ' return first non empty cell
    For i = UBound(rngAsArray, 1) To LBound(rngAsArray, 1) Step -1
        If rngAsArray(i, 1) <> "" Then
            getLastValueWithArrayLoop = rngAsArray(i, 1)
            Exit Function
        End If
    Next

    ' if no value in range set to false
    getLastValueWithArrayLoop = False
End Function

' **
' Check rngColumn for last value (exit if none found) and
' update rngDueDate then move one column to the right etc.
' This macro relies on the function getLastValueWithLoop.
' @param {Range} rngColumn First column range to get last value in
' @param {Range} rngDueDate First cell to update due date in
' Example call in macro:
' updateDueDateInEachColumn Range("B2:B6"), Range("B7")
Public Sub updateDueDateInEachColumn(rngColumn As Range, rngDueDate As Range)
    Dim rng As Range
    Dim lastValue As Variant

    ' Loop until column is empty
    Do
        ' Get last value of column range, returns false if no value found
        lastValue = getLastValueWithLoop(rngColumn)
        If lastValue = False Then
            ' Exit the loop if no value was found
            Exit Do
        Else
            ' Update due date
            rngDueDate = lastValue + 10 ' TODO: add your calculation here
        End If
        ' Offset column and due date range by one column
        Set rngColumn = rngColumn.Offset(, 1)
        Set rngDueDate = rngDueDate.Offset(, 1)
    Loop

End Sub

Пример использования функций внутри листа:

example usage

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...