powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Ошибка в простом коде
13 сообщений из 13, страница 1 из 1
Ошибка в простом коде
    #39293690
merkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Делаю на VBA в Excel построение графиков. Много графиков на одном.
Есть несколько столбцов в Excel. Первый - это координата X, остальные столбцы - это Y.
Количество строчек в столбце xk=1600.
Если в программе задавать количество строчек около 30, то нормально работает, а когда ставлю 1600,
вылезает ошибка: "Run-time error '1004' application-defined or object-defined error".
Как я понимаю, это из-за присвоения oRange = aryX.
А как поправить не знаю.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
Private Sub CommandButton1_Click()
Dim Xk As Integer
Dim Max As Double
Dim CurveNumber As Integer
Dim oRange, oRange2 As Range
Dim aryX As Variant
Dim i As Integer
Dim r As Long
Xk = 300

ActiveSheet.ChartObjects.Add(300, 250, 500, 200).Select
ActiveChart.ChartType = xlXYScatterSmoothNoMarkers

For CurveNumber = 1 To 5

Max = Cells(1, CurveNumber + 1)
  For i = 1 To Xk
    If Cells(i, CurveNumber + 1) > Max Then
     Max = Cells(i, CurveNumber + 1)
    End If
  Next i

oRange = Range(Cells(1, CurveNumber + 1), Cells(Xk, CurveNumber + 1))

aryX = oRange

For r = 1 To Xk
aryX(r, 1) = aryX(r, 1) * 2
Next r
oRange = aryX

    ActiveChart.SeriesCollection.NewSeries
    ActiveChart.SeriesCollection(CurveNumber).XValues = Range(Cells(1, 1), Cells(Xk, 1))
    ActiveChart.SeriesCollection(CurveNumber).Values = oRange
    
Next CurveNumber
    
End Sub
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39293758
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Начать с того, что необходимо точно определить тот оператор, при выполнении которого возникает ошибка.
Далее - присваивать переменной одного типа значение из переменной другого типа есть моветон. Автоконвертация типов не обязана уметь преобразовать что угодно во что угодно, да ещё и корректно.
А ещё - объекты следует квалифицировать полностью. Вот мало ли какая именно коллекция из многочисленных Cells будет использоваться кодом...
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39293779
merkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ошибку я исправил так: создал еще одну переменную и результат записал в нее.
Код: vbnet
1.
2.
3.
4.
    Set oRange2 = Range(Cells(1, MyCols(CurveNumber + 1)), Cells(Xk, MyCols(CurveNumber + 1)))
...
    oRange2 = aryX
    ActiveChart.SeriesCollection(CurveNumber).Values = oRange2



Но теперь возникла другая проблема. Хочу отнормировать графики на максимальное значение.
Оно считается верно. Но нормировки не происходит почему-то.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
Private Sub CommandButton1_Click()

Dim j, Xk, ColsNumber As Integer
Dim Max1 As Single
Dim CurveNumber As Integer
Dim c, oRange, oRange2 As Range
Dim aryX As Variant
Dim i As Integer
Dim r, rr As Long
Dim MyCols As Variant
MyCols = Array(0, 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50)

Xk = 1616
ColsNumber = 2
ActiveSheet.ChartObjects.Add(300, 250, 500, 200).Select
ActiveChart.ChartType = xlXYScatterSmoothNoMarkers

For CurveNumber = 1 To ColsNumber

Max1 = Cells(1, CurveNumber + 1)
  For i = 1 To Xk
    If Cells(i, CurveNumber + 1) > Max1 Then
     Max1 = Cells(i, CurveNumber + 1)
    End If
  Next i
Cells(1620, CurveNumber + 1) = Max1
Set oRange = Range(Cells(1, MyCols(CurveNumber + 1)), Cells(Xk, MyCols(CurveNumber + 1)))
Set oRange2 = Range(Cells(1, MyCols(CurveNumber + 1)), Cells(Xk, MyCols(CurveNumber + 1)))

aryX = oRange

For r = 1 To Xk
aryX(r, 1) = aryX(r, 1) / Max1

Next r
oRange2 = aryX

    ActiveChart.SeriesCollection.NewSeries
    ActiveChart.SeriesCollection(CurveNumber).XValues = Range(Cells(1, 1), Cells(Xk, 1))
    ActiveChart.SeriesCollection(CurveNumber).Values = oRange2
    
Next CurveNumber
    
End Sub
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39293805
merkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
С максимумом разобрался.

Теперь вопрос такой: как сделать, чтобы значения в ячейках не перезаписывались?
А то получается, что после расчетов, в ячейки записываются уже отнормированные значения.
Я вроде как их в ячейки не записываю, а только в переменную. А они почему-то оказываются в ячейках.


Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
Private Sub CommandButton1_Click()
MsgBox "Ïðèâåò ãðóïïàì 723, 726"
Dim j, Xk, ColsNumber As Integer
Dim Max1 As Single
Dim CurveNumber As Integer
Dim c, oRange, oRange2 As Range
Dim aryX As Variant
Dim i As Integer
Dim r, rr As Long
Dim MyCols As Variant
MyCols = Array(0, 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50)
'MyCols = Array(0, 2, 5, 8)
Xk = 1616
ColsNumber = 17
ActiveSheet.ChartObjects.Add(300, 250, 500, 200).Select
ActiveChart.ChartType = xlXYScatterSmoothNoMarkers

For CurveNumber = 1 To ColsNumber

Max1 = Cells(1, MyCols(CurveNumber))
  For i = 1 To Xk
    If Cells(i, MyCols(CurveNumber)) > Max1 Then
     Max1 = Cells(i, MyCols(CurveNumber))
    End If
  Next i
Cells(1618, CurveNumber) = Max1
Set oRange = Range(Cells(1, MyCols(CurveNumber)), Cells(Xk, MyCols(CurveNumber)))
Set oRange2 = Range(Cells(1, MyCols(CurveNumber)), Cells(Xk, MyCols(CurveNumber)))

aryX = oRange

For r = 1 To Xk
aryX(r, 1) = aryX(r, 1) / Max1

Next r

oRange2 = aryX

    ActiveChart.SeriesCollection.NewSeries
    ActiveChart.SeriesCollection(CurveNumber).XValues = Range(Cells(1, 1), Cells(Xk, 1))
    ActiveChart.SeriesCollection(CurveNumber).Values = oRange2
    
Next CurveNumber
    
End Sub
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39294233
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
merkinЯ вроде как их в ячейки не записываю, а только в переменную
а на что, по-Вашему переменная ссылается?
merkin
Код: vbnet
1.
2.
3.
4.
'назначили переменной oRange ссылку на диапазон
Set oRange = Range(Cells(1, MyCols(CurveNumber)), Cells(Xk, MyCols(CurveNumber)))
'назначили переменной oRange2 ссылку на диапазон
Set oRange2 = Range(Cells(1, MyCols(CurveNumber)), Cells(Xk, MyCols(CurveNumber)))


обращаю внимание - oRange и oRange2 это ссылки на один и тот же диапазон. Т.е. они равны. Т.к. это объект-ссылка на диапазон - то все действия с одним или вторым влияют на оба(oRange и oRange2) и на исходный диапазон Range(Cells(1, MyCols(CurveNumber)), Cells(Xk, MyCols(CurveNumber)))
потому как переменные эти - лишь ссылки на исходный диапазон, а не какая-то локальная и независимая копия диапазона. Иначе бы манипуляции со значениями таких объектов никак не отразились бы ни на графике, ни на листе.
И как следствие, назначение ячейкам массива oRange2 каких-то значений отразится и на oRange и на исходном диапазоне:
Код: vbnet
1.
2.
3.
oRange2 = aryX
'все равно, что записать так:
'Range(Cells(1, MyCols(CurveNumber)), Cells(Xk, MyCols(CurveNumber))) = aryX


учите матчасть, учите :)
по сути oRange2 вообще не нужен. Вы зря думали, что он будет работать независимо от исходного и от oRange.
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39294236
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
merkin,

по сути, Вам вероятно, можно так сделать. Заменить этот блок:
Код: vbnet
1.
2.
3.
4.
5.
oRange2 = aryX

    ActiveChart.SeriesCollection.NewSeries
    ActiveChart.SeriesCollection(CurveNumber).XValues = Range(Cells(1, 1), Cells(Xk, 1))
    ActiveChart.SeriesCollection(CurveNumber).Values = oRange2


таким:
Код: vbnet
1.
2.
3.
4.
' oRange2 = aryX 'это убираем, чтобы не изменять исходные данные ячеек
    ActiveChart.SeriesCollection.NewSeries
    ActiveChart.SeriesCollection(CurveNumber).XValues = Range(Cells(1, 1), Cells(Xk, 1))
    ActiveChart.SeriesCollection(CurveNumber).Values = aryX 'назначаем массив данных, а не ссылку на диапазон - это допустимо
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39295062
Фотография i45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
merkin,

Эта строка работать не будет.

oRange2 = aryX
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39295076
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
i45,

почему же? По умолчанию объект Range применяет свойство .Value. Т.е. запись равносильна такой:
Код: vbnet
1.
oRange2.Value = aryX


т.е. значения ячеек диапазона oRange2 будут заменены значениями массива aryX. Почему же это не должно работать?
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39295141
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Работоспособность (а если работоспособна - то правильность этой работы) этой конструкции зависит от типа переменной aryX.
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39295187
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akinaзависит от типа переменной aryX
Код: vbnet
1.
Dim aryX As Variant


поэтому работоспособность этой части у меня лично не вызывает вопросов :)
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39295199
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Variant - это общий тип. А для инициализироанной переменной это Variant/Что-то. И вот отэтого "что-то" всё изависит.
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39295292
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akina,

мы же приложенный код обсуждаем? Там нет причин, почему бы не работала строка oRange2.Value = aryX. Ведь переменная aryX объявлена с общим типом и далее по коду первое присвоение данных, которое идет это как раз назначение массива из диапазона ячеек.
Плюс не вижу причин неработы даже в том случае, если ранее по коду переменной передавалось значение иного типа. Вот, например, код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Sub ttttt()
    Dim arr
    arr = "hay!"
    MsgBox TypeName(arr)
    arr = 1208
    MsgBox TypeName(arr)
    arr = Range("A1:A10").Value
    MsgBox TypeName(arr)
    MsgBox IsArray(arr) 'точно массив? Массив
    arr = 10004536
    MsgBox TypeName(arr)
End Sub


будет работать без проблем, хотя переменной типа Variant по ходу кода назначаются значения разных типов. Т.е. опять же - в изначальном коде автора это не вызовет ошибку.
...
Рейтинг: 0 / 0
Ошибка в простом коде
    #39295396
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
The_Pristмы же приложенный код обсуждаем? Там нет причин, почему бы не работала строка oRange2.Value = aryX. Ведь переменная aryX объявлена с общим типом и далее по коду первое присвоение данных, которое идет это как раз назначение массива из диапазона ячеек.
Пардон, меня всегда смущает раздел - вернее, то, что именно в нём, а не в разделе MS Office, публикуются вопросы по VBA. Хотя тянет отвечать на них как на вопросы по VB.

Да, в данном конкретном случае, ибо Excel VBA, переменная aryX после присвоения ей объекта Range получает субтип Array of Variant. Возражения снимаются.
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Ошибка в простом коде
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]