2015-04-06 1 views
1

У меня есть определенная пользователем функция в VBA, которая записывает некоторые данные, вычисленные функцией. Место для записи данных будет ячейкой строки рядом с «ячейкой», где пользователь вызывает функцию VBA в листе Excel.Как записать данные в ячейки в VBA с указанием времени выполнения?

например: рассмотреть печать таблицы умножения для числа заданного пользователя

Public function Mul_Table(number as integer) 
    dim wb as string 
    dim ws as string 
    dim i as integer ,row_num as integer,column_num as integer 
    wb= activeworkbook.name 
    ws=activesheet.name 
    row_num = activecell.row 
    column_num =activecell.column 
    for i = 1 to 20 
     workbooks(wb).sheets(ws).cells(row_num+i , column_num).value = i*number 
    next i 
end function 

Теперь, когда я выполнил я получил проблему #value ошибки в ячейке, где функция называется. В отладке контроллер выдает ошибку в строке «workbooks(wb).sheets(ws).cell(row_num+i , column_num) = i*number» , но я не могу найти, почему это происходит неправильно.

+0

возможно дубликат [функции Excel VBA работает в Visual Basic, но терпит неудачу в Рабочий лист] (http://stackoverflow.com/questions/15646887/excel-vba-function-works-in-visual-basic-but-fails-in-workheet) –

ответ

2

Место для записи данных будет ячейкой строки рядом с «ячейкой», где пользователь вызывает функцию VBA в листе excel.

Это не может быть сделано с помощью пользовательской функции, вызываемой с рабочего листа. Вот почему вы получаете сообщение об ошибке #Value!.

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

Если останова и пошагово вы будете код, вы будете наблюдать, что она будет прервана, вероятно, на этой линии, если не раньше:

workbooks(wb).sheets(ws).cells(row_num+i , column_num).value = i*number 

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

Сделать стартовой Sub вместо функции, и он должен работать:

Public Sub Mul_Table() 
    dim number as INteger 

    dim wb as string 
    dim ws as string 
    dim i as integer ,row_num as integer,column_num as integer 

    number = Application.InputBox("Enter an integer value") 
    wb= activeworkbook.name 
    ws=activesheet.name 
    row_num = activecell.row 
    column_num =activecell.column 
    for i = 1 to 20 
     workbooks(wb).sheets(ws).cells(row_num+i , column_num).value = i*number 
    next i 
End Sub 
+0

отличный ответ, наконец, некоторое хорошее объяснение ограничений функций , Мой вопрос: может ли он это сделать, что UDF вводится в ячейку и внутри UDF, есть вызов подчиненного вам, но с аргументом, уже переданным в функцию, как первоначально требовалось OP? Таким образом, последовательность затем выглядит как 'function Mul_Table (число как целое)' then' вызывает Sub Mul_Table_other() ... code ... code ... end sub' then 'End function'. –

+0

@ BranislavKollár Почему бы не попробовать и не посмотреть, что происходит? Если это не сработает, возможны возможные обходные пути с использованием 'Application.Evaluate', которые вы можете найти здесь, в StackOverflow, но я бы не рекомендовал пытаться переопределить эти ограничения. Они созданы для (хорошей) причины. –

+0

http://stackoverflow.com/questions/15646887/excel-vba-function-works-in-visual-basic-but-fails-in-worksheet/15647054#15647054 –

0

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

  1. Подпрограмма для генерации таблицы умножения.

    
    Public Sub Mul_Table(number As Integer) 
        Dim i, row_num, column_num As Integer 
        For i = 1 To 20 
         ActiveCell.Offset(i, 0).Value = i & " x " & number & " = " & i * number 
         'ActiveCell.Offset(i, 1).Value = i * number 'Uncomment if you want the result in a new column 
        Next 
    End Sub 
    
  2. Подпрограмма, которая генерирует таблицу умножения на основе пользовательского ввода.

    
    Sub getMultiplicationTable() 
        mynumber = InputBox("Enter the number.", "Enter number") 
        Call Mul_Table(CInt(mynumber)) 
    End Sub 
    
  3. Sub рутина, которая генерирует таблицу умножения 2

    
    Sub getMultiplicationTableOfTwo() 
        Call Mul_Table(2) 
    End Sub 
    
0

За то, что вы делаете, вы можете с помощью события worksheet_change, который будет срабатывать, когда что-то введено, то вы можете иметь код проверяет адрес цели (Target.Address), чтобы узнать, введут ли они данные, где вы хотите, и тогда выполните свою задачу.

Вот пример, который я только что залетела для вас:

Private Sub Worksheet_Change(ByVal Target As Range) 
Dim X As Long 
If Target.Address = "$A$1" Then 
    Application.EnableEvents = False 
    For X = 1 To 20 
     Range("B" & X).Value = Range("A1").Value * X 
    Next 
    Application.EnableEvents = True 
End If 
End Sub 

падения, что в VBE на уровне рабочего листа, а затем ввести номер в A1.

Существует несколько других способов сделать это, вы можете опубликовать весь диапазон за один раз, а не зацикливаться (я оставил цикл, как вы сказали, вы учитесь, и вот как вы пытались это сделать)

Нет ошибок там или что-то в этом роде, но я уверен, что вы могли бы оценить эту часть, исходя из того, какие критерии вы хотите.

В качестве альтернативы вы можете сделать это с помощью формул что-то, как и в В1:

=$A$1*ROW(B1) 

Затем перетащите вниз и поставить номер в A1