Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Excel VBA (часть 2)

Автор: Olive77
Дата сообщения: 24.10.2008 10:19
а существует ли какой-нибудь элегантный способ (без использования error handler и написания собственной функции IsArrayEmpty) определить, был ли инициирован массив (по аналогии с IsEmpty для переменных)?

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

Код:
Public Function IsArrayEmpty(aArray() As Variant) As Boolean

On Error Resume Next
IsArrayEmpty = UBound(aArray)
IsArrayEmpty = CBool(Err.Number <> 0)

End Function
Автор: ScorpionS
Дата сообщения: 24.10.2008 10:52
Помогите решить след. задачу, пожалуйста.
Есть лист "Val" с достаточно большой таблицей. Есть четыре параметра:
Par1 (ячейка N1619), Par2 (N1620), Par3 (N1621) и Par4 (N1622).
И есть итоговый коэффициент REZ (ячейка S1617), значение которого зависит от этих четырех параметров, т.е. меняешь какой-нибудь параметр и REZ пересчитывается. Нужно просчитать все значения REZ при изменении значений параметров - при этом у каждого из них свой диапазон:
Par1 = от 10 до 60, Par2 = от 1 до 10, Par3 = от 0 до - 15, Par4 = от 0 до 5
Не трудно подсчитать, что получается почти 50 000 комбинаций и в ручную это сделать крайне трудоемко, поэтому хотелось бы автоматизировать этот процесс. В идеале нужно, чтоб макрос просчитывал значение REZ и записывал его на другом листе "Val_Test" в ячейку A1, затем прочситывал следующее значение и записывал его в ячейку A2, и т.д. Вроде в Excel больше 65 тыс. строк, так что должно хватить. Возможно ли реализовать такое и будет ли реально это работать (не зависнет ли Excel от таких расчетов)?
Автор: q1wed
Дата сообщения: 24.10.2008 11:06
ScorpionS не думаю что зависнет, вот только полученные значения лучше помещать не как у меня в коде - в ячейки, а в массив - тогда макрос раз в 10 быстрей отработает.

Код: Sub макрос()
Dim i, par1, par2, par3, par4 As Integer
i = 1
For par1 = 10 To 60
For par2 = 1 To 10
For par3 = 0 To 15
For par4 = 0 To 5
Cells(i, 1) = f(par1, par2, par3, par4) ' лучше помещать в массив а не в ячейки
i = i + 1
Next
Next
Next
Next
End Sub
Автор: ScorpionS
Дата сообщения: 24.10.2008 12:38
q1wed, спасибо за оперативный ответ, но я вынужден задать пару уточняющих вопросов, поскольку не силен в VBA:
во первых в первом вопросе понятия par1, par2, par3 и par4 были условными, чтоб вопрос был понятен. как мне сделать, чтобы этот макрос понимал, о каких значениях идет речь? Может быть нужно присвоить соответствующим ячейкам ИМЯ? Или в самом макросе нужно приписать этим ячейкам понятия par1, 2, 3 и 4? Если так, то подскажи, пожалуйста, как это сделать. А вот рекомендацию "лучше помещать в массив а не в ячейки" вообще не понял. Можно поподробней, что и где надо поменять, добавить и т.п.
Автор: MaximuS G
Дата сообщения: 24.10.2008 13:21
q1wed
Можно вопросик, как мне указать в функции InStrRev что бы подсчет начался не с конца а с начала... InStrRev(string1, "s",[-1]) так стандарт, а меняю на 0 - ошибка, на 1 - выдает ноль...
И по-поводу кавычек, что-то не выходит:
ни так msgbox (""privet"" ), ни так a=""", изменяет на a = """" ... СПС за ответ

Прочитал сообщение сверху, стало интересно что такое
... = f(par1, par2, par3, par4), имею ввиду что за функция
Автор: q1wed
Дата сообщения: 24.10.2008 13:28
ScorpionS
макрос переберет все значения параметров в указанных пределах, во всевозможных сочетаниях друг с другом. И на основаниии перебора выдаст ~50000 значений. перебирать будет целые числа с шагом 1, то есть для par4 это 0,1,2,3,4,5.

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

Добавлено:
MaximuS G
InStrRev - с конца
InStr - с начала

Добавлено:

Цитата:
... = f(par1, par2, par3, par4), имею ввиду что за функция
))))) ну просто типа: f(x) функция которая вычисляется на основании par1, par2, par3, par4 - я это имел ввиду

Добавлено:
MaximuS G, nopoxz по поводу кавычек: использовал двойные кавычки когда писал макрос-скрипт на VBS - вот уж не думал, что в VBA другие принципы..............

Ещё Добавлено:
Да шо Вы меня в заблуждение вводите своми кавычками!!! Все работает как надо!!!!
Двойные кавычки имеется ввиду, что одна пара кавычек отвечает за то что это текст а каждая пара кавычек заключенная в эти кавычки - считается за одну кавычку. Пример:
Код: MsgBox ("Превед ""Медвед""")
Автор: MaximuS G
Дата сообщения: 24.10.2008 13:48
q1wed
Спасибо
Автор: ScorpionS
Дата сообщения: 24.10.2008 14:07
q1wed, как раз параметры принимают эти значения по такому принципу (par4 это 0,1,2,3,4,5), но вся загвоздка как раз в функции f(x), которая вычисляется на основании par1, par2, par3, par4. Эту функцию (весь алгоритм расчета коэффициента REZ) не получится прописать в VBA, по крайне мере я не представляю как это сделать. Чтобы было понятней я выложил файл сюда http://ifolder.ru/8721382 пароль для скачивания "ru-board" (баз кавычек). Повторюсь. Нужно значение коэффициента REZ (в закачанном файле это ячейка N188) при различных комбинациях 4 параметров вставлять на другой лист "Val_Test" в ячейки столбца A.
Автор: q1wed
Дата сообщения: 24.10.2008 15:13
ScorpionS файл вместе с макросом.
Скорость выполнения черепашечья((((((((. Можно на ночь оставлять на просчет. Ускорить можно, но для этого нужно максимально отвязаться от взаимодействия макроса с ячейками на листе. Судя по логике задачи сделать это будет не просто.....
Вообщем если это разово - оставляй так, если придется часто выполнять то, надо что-то в корне менять и переводить формулы в ячейках в код VBA
!PS макрос запускать находясь на листе val_test, остановить выполнение можно нажав ESC

Код: Sub макрос()
Dim i, par1, par2, par3, par4 As Integer
i = 1
For par1 = 10 To 60
For par2 = 1 To 10
For par3 = 0 To 15
For par4 = 0 To 5
Range("val!N183").Value = par1
Range("val!N184").Value = par2
Range("val!N185").Value = par3
Range("val!N186").Value = par4
Cells(i, 1) = Range("val!N188")
i = i + 1
Next
Next
Next
Next
End Sub
Автор: Olive77
Дата сообщения: 24.10.2008 15:44
q1wed
можно и этот вариант несколько ускорить.


Код:
Sub макрос()
Dim i, par1, par2, par3, par4 As Integer

Application.ScreenUpdating = False
i = 1
For par1 = 10 To 60
Application.StatusBar = "par1: " & par1

For par2 = 1 To 10
For par3 = 0 To 15
For par4 = 0 To 5
Application.Calculation = xlCalculationManual
Range("val!N183").Value = par1
Range("val!N184").Value = par2
Range("val!N185").Value = par3
Range("val!N186").Value = par4

Application.Calculation = xlCalculationAutomatic
Worksheets("Val_Test").Cells(i, 1) = Range("val!N188")
i = i + 1
Next
Next
Next
Next

Application.Calculation = xlCalculationAutomatic
Application.StatusBar = "Ready"
Application.ScreenUpdating = True
End Sub
Автор: MaximuS G
Дата сообщения: 24.10.2008 15:59
q1wed
да, так работает
Автор: ScorpionS
Дата сообщения: 24.10.2008 17:22
q1wed, Olive77 Спасибо вам огромное. Очень помогли. Вроде работает, хотя и медленно, но я на сверх быстроту и не расчитывал, понимая сложность расчетов.

Добавлено:
q1wed, подскажи, а как можно в строчке

Цитата:
For par1 = 10 To 60

цифры 10 и 60 заменить значениями в ячейках N200 и Т201 соответственно? Ну допустим, если хочется выставить другой диапазон по этому параметру, и чтоб каждый раз не вносить изменения в макросе, а просто вбить в эти ячейки другие значения.
Я правильно понимаю, что это должно иметь след. вид

Код: For par1 = Range("val!N200") To Range("val!N201")
Автор: Olive77
Дата сообщения: 24.10.2008 20:01
ScorpionS

Цитата:
Код:
For par1 = Range("val!N200") To Range("val!N201")

или как то по другому?

угу


Цитата:
Application.ScreenUpdating = False

отключает экран на время вычислений


Цитата:
Цитата:
Application.StatusBar = "par1: " & par1

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

значит строка состояния не активирована
--> в начале макроса вставь
Application.StatusBar =True


Цитата:
Да..., и еще. Olive77, что дописать в твоем коде, чтоб в самом начале (перед расчетом) очищались все строки на листе Val_Test, кроме строки 1 (это шапка).

Worksheets("Val_Test").range("A2:A" & Worksheets("Val_Test").range("A2").end(xlDown).Row).ClearContents
Автор: ScorpionS
Дата сообщения: 24.10.2008 20:39
Olive77

Цитата:
отключает экран на время вычислений

это как-то ускоряет процесс расчета?

Цитата:
Worksheets("Val_Test").range("A2:A" & Worksheets("Val_Test").range("A2").end(xlDown).Row).ClearContents

что не срабатывает, очищает только первую ячейку. я сделал так

Код: Worksheets("Val_Test").range("A2:A65000").ClearContents
Автор: Olive77
Дата сообщения: 24.10.2008 21:10
ScorpionS

Цитата:
это как-то ускоряет процесс расчета?

процесс расчета нет, но поскольку матрица экрана имеет определенное время задержки при выводе информации, то вот оно и экономится


Цитата:
что не срабатывает, очищает только первую ячейку. я сделал так

должно работать
Автор: YuriyRR
Дата сообщения: 25.10.2008 06:55
Через OLE Drag & Drop перетаскивается текст в ячейку Exel из другой прилады, но в обьединенную ячейку не падает, а выдается ошибка 'не могу изменить часть обьединенной ячейки'.
кто может подсказать как такое реализовать, в принципе не обязательно через OLE
Автор: q1wed
Дата сообщения: 25.10.2008 12:28
ScorpionS, Olive77 увеличил скорость выполнения макроса более чем в полтора раза. Добавленные места помечены зеленым, оптимизированные синим. Таймер добавлен для оценки скорости выполнения.

Код: Sub макрос()
Dim i, par1, par2, par3, par4 As Integer, t As Long, arr(1 To 49000, 0) As Single
t = Timer

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
i = 1
For par1 = 10 To 60
Application.StatusBar = "par1: " & par1
Range("val!N183").Value = par1

For par2 = 1 To 10
Range("val!N184").Value = par2

For par3 = 0 To 15
Range("val!N185").Value = par3

For par4 = 0 To 5
Range("val!N186").Value = par4

Application.Calculation = xlCalculationAutomatic
' Закомментировано Worksheets("Val_Test").Cells(i, 1) = Range("val!N188")
arr(i, 0) = Range("val!N188")
Application.Calculation = xlCalculationManual
i = i + 1
Next
Next
Next
Next

Worksheets("Val_Test").Range("A2:A49000") = arr
Application.Calculation = xlCalculationAutomatic
Application.StatusBar = "Ready " & Timer - t
Application.ScreenUpdating = True
End Sub
Автор: marklar
Дата сообщения: 26.10.2008 00:05
Добрый день! Подскажите, пожалуйста, кто знает, как в Excel VBA получить данные из какой-либо ячейки построчно (т.е. при включенном Word wrap)? А то все ломаю голову, никак не могу придумать способ... Может это невозможно? Заранее спасибо.
Автор: q1wed
Дата сообщения: 26.10.2008 02:22
marklar А как образован перенос строки? Если через Alt+Enter то можно отловить на Chr(10). А если через WrapText тогда, думаю, только через ширину строки высчитывать количество символов, что имхо геморно будет....
Автор: marklar
Дата сообщения: 26.10.2008 08:45
q1wed В том то и дело, что интересует WrapText... Excel ведь чем-то руководствуется (может настройками драйвера принтера или еще чем?), когда слова в ячейке на следующую строку переносит. Вот я и думаю, каким же образом из VBA до этого можно докопаться... Похоже сэр Билл Гейтс этого в VBA просто не предусмотрел, и учитывая что все символы еще и разной ширины, а может еще и разных размеров, то это получается действительно геморно. А хотелось бы как-то попроще извратиться....

Автор: nick7inc
Дата сообщения: 26.10.2008 12:58
marklar

Цитата:
Excel ведь чем-то руководствуется, когда слова в ячейке на следующую строку переносит.

Думаю, что он руководствуется только шириной конкретных символов. Под Win я не программировал, но в Allegro (библиотека для C++) есть подобные функции для вычисления ширины строчки из символов (или конкретных знаков) в пикселях , думаю, что в Windows аналогично сделано. Проблема в том, что есть шрифты, которые имеют фиксированную ширину знака, а есть шрифты с переменной (видно, если сравнивать точки и запятые с какими-нибудь большими буквами типа Щ Ю W).

Мои варианты:

1)Вам, IMHO, проще взять шрифт с фиксированной шириной знаков (Courier New, если не ошибаюсь) и тогда вычислять ширину знаков вам не составит труда. У кажного знака ширина будет постоянна, её можно в какую-нибудь константу записать.

2)Либо (ну уже совсем в качестве бредовой идеи), надо измерять ширину знаков непрямым методом (будет медленно), например, создавая из надписи картинку (копировать надпись или текст, Вставить как рисунок, измерить ширину объекта-рисунка). Так вы можете сделать таблицу, в которой будут приведены хар-ки всех знаков какого-нибудь шрифта заданного размера, чтобы потом их можно было использовать в программе.

3) Копать в сторону WinAPI, искать функцию, которая бы вам посчитала ширину знака прямым методом.
Автор: dneprcomp
Дата сообщения: 26.10.2008 22:40
marklar
Посмотри TextWidth Method. Учитывая ScaleMode, положение пробелов и длину ячейки, можно получить примерную точку перехода строки.
Автор: marklar
Дата сообщения: 27.10.2008 01:28

Цитата:
Посмотри TextWidth Method

Чет не нашел такого Где посмотреть? У объекта Range нашел только свойства Text и Width, а метода TextWidth нету...
Автор: comkmsboy
Дата сообщения: 27.10.2008 04:30
Ребята!!! Дайте пожалуйста алгоритм перевода числа в пропись!!! Очень нужно!
Автор: q1wed
Дата сообщения: 27.10.2008 06:34
comkmsboy
надстройка Excellerator (c) Michael Zemlanukha & Maxim Shemanarev
макрос Num2String
Автор: MaximuS G
Дата сообщения: 27.10.2008 12:41
Добрый день!
Подскажите как получить координаты первой и последней ячейки из Selection ?
П потом их вставить в формулу
ActiveCell.FormulaR1C1 = "=RANK(RC[-1],R2013C35:R2114C35)" на месте диапазона.
СПС
Автор: q1wed
Дата сообщения: 27.10.2008 14:01
MaximuS G Selection.Address
Автор: MaximuS G
Дата сообщения: 27.10.2008 15:04
q1wed
Спасибо, только как его в формулу вставить ?
Автор: q1wed
Дата сообщения: 27.10.2008 15:33
ну хотя бы может так:
adr = "=RANK(RC[-1]," & Selection.Address(ReferenceStyle:=xlR1C1) & ")"
ActiveCell.FormulaR1C1 = adr
Автор: MaximuS G
Дата сообщения: 27.10.2008 15:49
q1wed
Супер, спасибо, так даже сразу решилась моя проблема с фиксацией ячеек, а можна тогда спросить вообще как фиксировать ячейки используя формат " & variable & " ..

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133

Предыдущая тема: Написание своего HyperTerminal для считывания данных


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.