Страницы: 1 2 След.
RSS
ReDim Preserve a(1 To i, 1 To 5) неправильно. Почему?
 
Создаю тест в VBA. есть несколько вопросов    
1)первый, как написать код,который проверял бы массив на совпадения?    
2)Sub Test()    
Dim a(1 To 1, 1 To 5)    
Dim x As Integer    
Dim y As Integer    
Dim z As Integer    
Dim i As Integer    
Dim m As Integer    
 
For i = 2 To 21    
x = Int((108 * Rnd) + 2)    
y = Int((108 * Rnd) + 2)    
z = Int((108 * Rnd) + 2)    
m = Int((108 * Rnd) + 2)    
 
ReDim Preserve a(1 To i, 1 To 5)    
a(i, 1) = Cells(x, 1)    
a(i, 2) = Cells(x, 2)    
a(i, 3) = Cells(y, 2)    
a(i, 4) = Cells(z, 2)    
a(i, 5) = Cells(m, 2)    
 
Next i    
MsgBox (a(1, 1))    
 
End Sub    
 
собственно вот написаный мной код, но эксель ругается на строчку " ReDim Preserve a(1 To i, 1 To 5)"    
почему и как исправить?  
 
 
прилагаю файл, со всей инфой
 
Изменять можно только границу последней размерности, т.е. у Вас только UBound (a,2).
 
а можно по-понятнее и по-подробнее? я в vba новичок
 
Сегодня ве штатные отвечатели по VBA отсутствуют, а тут вопросы... Придется вычесть из зарплаты. А мне премию :)  
 
ReDim Preserve а(1 To i, 1 To 5)  
Вы хотите изменить границу первой размерности "от 1 до i". В VBA ограничение: при переопределении массива можно изменять только последнюю размерность, здесь - разрешается измениять "5". Вариант ReDim Preserve а(1 To 1, 1 To i) правильный с точки зрения программы, но Вам такое не нужно...  
 
Неплохая тема для начинающих:  
<EM>http://www.planetaexcel.ru/forum.php?thread_id=36781</EM>
 
В частном случае верхний индекс двумерного массива можно изменить примерно так:  
 
Sub tttt()  
Dim u, l, l1, i, j  
ReDim a(5, 3)  
For i = 0 To 5: For j = 0 To 3: a(i, j) = i & j: Next: Next  
a = WorksheetFunction.Transpose(a)  
l = LBound(a): u = UBound(a): l1 = LBound(a, 2)  
ReDim Preserve a(l To u, l1 To 9)  
a = WorksheetFunction.Transpose(a)  
End Sub  
 
Конкретно Ваш код.  
В первое строке Вы определяете статический массив (Dim a(1 To 1, 1 To 5) )ю Для него ReDim не работает. Что бы можно было изменять размеры, либо Dim a(), а потом по ходу ReDim a(1 to i, 1 to 5), (без Preserve), либо через Transpose, тогда можно и с Preserve/
 
ps Dim a() объявлять необязательно. В нужном месте можно сразу ReDim a(1 to i, 1 to 5)
 
самое интересное - в примере из первого поста ReDim вообще не нужен.  
автор пытается переопределить размеры массива в цикле 20 раз и в конце концов должен получить массив из 21 строки и 5 столбцов.  
 
проще, правильнее и быстрее написать просто и один раз:  
Dim a(1 To 21, 1 To 5)  
 
 
пс. vikttur'у выписать две премии - за VBA и ежедневное+еженощное дежурство. но - за счёт заведения :)))
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
{quote}{login=Михаил С.}{date=26.05.2012 10:09}{thema=одуванчик,}{post}Sub tttt()  
Dim u, l, l1, i, j  
ReDim a(5, 3)  
For i = 0 To 5: For j = 0 To 3: a(i, j) = i & j: Next: Next  
a = WorksheetFunction.Transpose(a)  
l = LBound(a): u = UBound(a): l1 = LBound(a, 2)  
ReDim Preserve a(l To u, l1 To 9)  
a = WorksheetFunction.Transpose(a)  
End Sub  
{/post}{/quote}  
Я, конечно, понимаю, что многие из присутствующих здесь пишут, что называется "на коленке", но и на коленке можно писать РАЗБОРЧИВО.  
Вы код в момент написания пытаетесь обсфуцировать? Глупая затея. Для этого есть специальные программы. А подобным стилем Вы создаете проблемы в первую очередь себе.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
"проверял бы массив на совпадения?" - какой массив? Совпадения с чем?  
Задача стандартная, уже столько раз решали... Подход обычно совсем другой.  
По поводу preserve - я стараюсь не использовать. Процесс не из быстрых, если повторять часто, и массив нарастает большой - то уже даже становится заметно...
 
{quote}{login=nerv}{date=26.05.2012 11:38}{thema=}{post}Вы код в момент написания пытаетесь обсфуцировать? Глупая затея. Для этого есть специальные программы. А подобным стилем Вы создаете проблемы в первую очередь себе.{/post}{/quote}  
Поискал в яндексе "обсфуцировать" - так и не понял, что это значит.    
nerv, а что Вам не нравится? Нет комментариев? - так я не умею их составлять. Мне легче сделать, чем рассказать как...
 
Поищите "обфускация" :)
 
For i = 0 To 5: For j = 0 To 3: a(i, j) = i & j: Next: Next  
 
я часто тоже так пишу.  
причем именно "для себя". на форумах - оч.редко, но бывает.  
и считаю такую запись более оправданной, логичной и удобной, чем запись того же самого в "классические" пять строк.  
 
почему?  
да потому что всё это дело представляет собой одну логическую единицу кода, или "кирпичик", выглядит компактно, занимает на экране одну строчку и позволяет на том же экране увидеть больше строчек, соседних с данной, а не елозить вверх-вниз по размазанному коду.  
 
пс. кроме "обфускации", я знаю ещё такое умное слово, как "догматизм" :)
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Догматизм здесь ни при чем.  
Разбираться в такой записи труднее. Особенно новичкам.  
Не так давно разбирал код календаря, так вот именно такие записи вводили в ступор, заставляя вчитываться в строки и держать в голове логические связи.  
 
Считаю, что лучше все-таки писать прозрачно, да еще и с пустыми строками между блоками  операторов, циклами... Хотя две-три строки типа  
If...: MsgBox  
или  
Sub...: Show...: End Sub  
еще можно одной строкой записать.  
 
P.S. А одуванчика-то ветром унесло :)
 
{quote}{login=vikttur}{date=27.05.2012 01:44}{thema=}{post}Хотя две-три строки типа  
If...: MsgBox  
или  
Sub...: Show...: End Sub  
еще можно одной строкой записать.{/post}{/quote}  
мммда?.. :)  
а вот сейчас вернётся в тему мой тёзка (nerv) и скажет, что - НЕТ! нифига недопустимо.  
и будет по-своему прав, потому что ему так удобно.    
 
а мне - неудобно.  
простой код размазывается на сотни строк, вместо десятков.  
 
на вкус и цвет, как говорится...  
но "догматизм" - это было к тому, что любую хорошую идею можно довести до абсурда.  
 
можно именовать переменные в "телеграфном" стиле: i, x, nMax  
можно записать так: intCounter, lngQuantity, lngMaxValue  
а можно так: Счётчик_Цикла_для_Поиска, Количество_Хрен_знает_чего_Но_ОЧЕНЬ_нужного, Максимальное_количество_Хрен_знает_чего_Но_ОЧЕНЬ_нужного  
 
опять-таки: мне удобнее первый вариант, nerv'у - второй, а кому-то - третий.  
 
ещё пример - именованные параметры функций, свойств и методов.  
я пишу:  
set c=r.find(what:=s, lookin:=xlpart, lookat:=xlwhole, matchcase:=true)  
 
а кому-то "правильнее" (и он от этого счастлив) написать так:  
Set rngFounded=rngGteMyBudemIskat.Find( _  
 What:=strWhatNamNadoNaiti, _  
 LookAt:=xlWhole, _  
 LookIn:=xlPart, _  
 MatchCase:=True, _  
 )  
 
а кто-то напишет    
sheets(1).protect "xyz",,,,1  
и для него очевидно, что это - UserInterfaceOnly включилсо.  
 
ну и... ради Бога, как говорится :)  
 
 
но я, блин, не понимаю, зачем писать так:  
Range("A1").Copy Destination:=...  
 
ведь там всего один параметр!!! :)))
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
спасибо за подсказки, он хотя бы перестал ругаться на неправильность кода)  
 
про проверку на совпаденияю Объясню подробнее. Я должен создать тест. Я написал код, который выбирает случайным образом из списка названия элементов. Но элементы могут повторятся, этого не должно быть. Мне нужен код,который проверял бы столбец, ну или массив,не знаю как правильнее сказать, на то,есть ли одинаковые ячейки, и если есть, то заменить эту ячейку на другую случайную. Надеюсь, объяснил нормально(
 
{quote}{login=одуванчик}{date=27.05.2012 12:19}{thema=}{post}... Мне нужен код,который проверял бы столбец, ну или массив,не знаю как правильнее сказать, на то,есть ли одинаковые ячейки, и если есть, то заменить эту ячейку на другую случайную. Надеюсь, объяснил нормально({/post}{/quote}Надо использовать словарь или коллекцию - так быстрее. Впрочем, если у вас ячеек около сотни, то пойдет любой способ.  
 
зы В третьем модуле, и макросе  Table(), Вы задаете переменные  
Dim Row As Integer  
Dim Column As Integer  
Слова Row и Column служебные, их использовать в качестве имен переменных нельзя.  
Если очень хочется, то MiRoW; Row_; Row1 и т.п.
 
Danger! This message contains many letters.  
 
 
Hugo )  
 
 
Михаил С., комментарии здесь не при чем.  
 
 
[ikki]>кроме "обфускации", я знаю ещё такое умное слово, как "догматизм" :)
Раз уж мы перешли на "измы" : ) , я тоже скажу - "рационализм".  
 
[ikki]>я часто тоже так пишу.
[ikki]>For i = 0 To 5: For j = 0 To 3: a(i, j) = i & j: Next: Next
Что происходит в голове, когда мы пытаемся прочитать эту строчку? Да тот же Split( string , ":" ). Зачем в пустую напрягать свой мозг?  
 
Вместо того, чтобы сконцентрироваться на логике программы, происходит разбор стоки - отвлечение на мелочи, за которым, нередко, теряется суть.  
 
 
[vikttur]>считаю, что лучше все-таки писать прозрачно
солидарен. Свеженаписанный код, даже такой, читается легко (для автора), но если к нему придется вернуться через некоторый промежуток времени, произойдет все то, что я описал выше, т.е. время на разбор строки + время на понять логику.  
 
 
[ikki]>а вот сейчас вернётся в тему мой тёзка (nerv) и скажет, что - НЕТ! нифига недопустимо.
конечно, скажет : ) Могу даже пример забавный привести.  
Тебе надо сходить в магазин за хлебом. Ты можешь:  
а) просто взять и сходить  
б) идти, подпрыгивая через каждые два шага  
Что выберешь? В варианте б) появляется возможность позабавить прохожих)  
 
Кстати, такой стиль программирования еще называют - говнокод. Это не камень в огород Михаила, а информация в целом.  
 
[ikki]>а кому-то "правильнее" (и он от этого счастлив) написать так:
[ikki]>Set rngFounded=rngGteMyBudemIskat.Find( _
[ikki]>What:=strWhatNamNadoNaiti, _
[ikki]>LookAt:=xlWhole, _
[ikki]>LookIn:=xlPart, _
[ikki]>MatchCase:=True, _
[ikki]>)
сейчас объясню почему. Во-первых, читаемость лучше, во-вторых, сразу видно, какой параметр передаем.  
 
еще существует следующий стиль (если позволит форум)  
Set rngFounded = rngGteMyBudemIskat.Find(What:= strWhatNamNadoNaiti, _  
______________________________________LookAt:= xlWhole, _  
______________________________________LookIn:= xlPart, _  
______________________________________MatchCase:= True)  
 
 
[ikki]>а можно так: Счётчик_Цикла_для_Поиска, [ikki]>Количество_Хрен_знает_чего_Но_ОЧЕНЬ_нужного, [ikki]>Максимальное_количество_Хрен_знает_чего_Но_ОЧЕНЬ_нужного
есть такое понятие как "избыточность"  
 
 
[ikki]>ещё пример - именованные параметры функций, свойств и методов. я пишу:
[ikki]>set c=r.find(what:=s, lookin:=xlpart, lookat:=xlwhole, matchcase:=true)
тот же парсинг в голове. Для этого и придумали визуально наглядную форму записи.  
 
 
[vikttur]>Не так давно разбирал код календаря, так вот именно такие записи вводили в ступор, заставляя вчитываться в строки и держать в голове логические связи.
Это один из возможных вариантов. Другой - нормально оформить код.  
 
 
смысл моей терады - не надо усложнять себе жизнь. Пусть некоторые считают, что им так проще. Как происходит на самом деле, обозначил выше.  
 
За себя скажу: сейчас с однобуквенными переменными не пишу. Счетчик - counter, счетчик строк - rowsСounter (верблюжий стиль, но не в этом суть). Использую оформление. Не объявляю переменные в одной строке через запятую. Забыл о существовании двоеточия для записи в одну строку. Одно строчный If  использую крайне редко, исключительно в тех местах, где он очевиден, например, перед End Sub : ) Использую "отступы вложенности", "отступы отделения логических блоков". Комментарии - наше все )
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
[Михаил С]> Слова Row и Column служебные, их использовать в качестве имен переменных нельзя
 
с чего вы взяли? )
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
{quote}{login=nerv}{date=27.05.2012 01:43}{thema=Re: }{post}[Михаил С]> Слова Row и Column служебные, их использовать в качестве имен переменных нельзя
 
с чего вы взяли? ){/post}{/quote}Скажем более мягко - не желательно.    
С чего взял? - да из Ваших же постов в ЭТОЙ теме.  
 
зы. Код, который я привел, я писал для себя, для проверки "мыслей". а строка  
For i = 0 To 5: For j = 0 To 3: a(i, j) = i & j: Next: Next  
вообще внесена последней, что б массив был не пустой.
 
>Скажем более мягко - не желательно.    
почему? )  
 
>С чего взял? - да из Ваших же постов в ЭТОЙ теме.  
где такой? Покажите )
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
nerv, спасибо за столь подробный ответ :)  
но я писал:  
 
>> ему так удобно.  
>> а мне - неудобно.  
 
и  
 
>> на вкус и цвет, как говорится...  
 
и  
 
>> ну и... ради Бога, как говорится :)  
 
 
спорить вообще не о чем.  
даже обсуждать - тоже нечего.  
 
я высказал свою т.зр. и то, что мне удобно, ты - свою.  
мне было интересно, но менять ничего не собираюсь.  
советовать кому-либо что-либо - тем более.  
 
пс.  
улыбнуло вот это:  
[ikki]> set c=r.find(what:=s, lookin:=xlpart, lookat:=xlwhole, matchcase:=true)
[nerv]> тот же парсинг в голове. Для этого и придумали визуально наглядную форму записи.
 
nerv, а сложносочиненные и (о,боже!) сложноподчиненные предложения в художественной литературе - тоже неряшливость и парсинг? :))
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Привет тезкам :-) и всем, кто в теме (этой).  
Мои "тараканы":  
1. Обязательно описание всех переменных (Dim A, Private B, Pablic XYZ);  
2. Обязательно все имена переменных начинаю с ПрописнойБуквы (даже если идентификатор - одна буква: I, J, K).  
Дальнейший код набираю строчными: VBA-редактор, если слово ему известно, сам исправляет строчные на Прописные,  
а если я ошибусь и наберу неизвестную редактору абракадабру - замены первой маленькой буквы на Большую не произойдёт -    
вижу, возвращаюсь, и перебиваю "неприличное" слово.  
Если VBA для всех встроенных имён операторов, процедур и свойств объектов, придерживается именно  
этого правила (первой заглавной (исключение - константы)), какой смысл нарушать этот порядок ?  
Избегаю (по этой же причине) венгерской (префиксной) нотации: iRow - это Integer или Long ?  
Если назову LRow, L - это префикс или сокращение Last ?  
Надо вспомнить кто такой LRow - подгляжу в разделе описаний (см. пункт 1.) (ПКМ на слове->Definition).  
3. Объявление типа переменной с добавлением специального знака в конце имени (K%, Total#, ... ) -    
считаю атавизмом бейсиков. Всё равно после Txt$ придётся писать MyRange As Range - для объектных типов нет спецзнаков -  
дискриминация по типовому признаку ! :-)  
 
PS: ИМХО.
 
привет )  
 
ikki, удобно/не_удобно здесь не при чем. Скорее правильно или не правильно (по моему мнению).  
 
Спорить не собирался. Кажется, мы вообще не соприли в этой теме.  
Просто пытаюсь показать почему делать правильно лучше, чем неправильно.  
Лучше в первую очередь для кодера (т.е. для себя)  
 
>nerv, а сложносочиненные и (о,боже!) сложноподчиненные предложения в художественной литературе - тоже неряшливость и парсинг? :))  
В программировании сложносочинять (судя по моему скромному опыту) надо только алгоритмы. Все остальное должно служить для облегчения процесса их создания.  
Еще несколько примеров.  
Сперва устный: есть такая штука, как "таблица умножения". Почему она именно таблица? Для удобства восприятия. Просто представь, что она записана в строку через любой разделитель.  
Примеры кода. Далеко ходить не буду, возьму тот же Find со всеми параметрами.  
 
Set Range = Range.Find("string", Range("A1"), True, xlWhole, xlByColumns, xlPrevious, True, True, Null)  
 
Что надо сделать, чтобы прочитать эту строку?  
1. Вспомнить, что обозначает каждый по счету параметр.  
2. Сверить в мозгу то, что вспомнил с тем, что передаешь.  
3. Разобрать по разделителям (отсчитать запятуйки. Малоли какая-то одна пропущена и тогда ай-яй-яй)  
4. Если на каком то возник ступор (например, засомневался, правильный ли аргумнет передаешь), еще раз п.1 затем п.2.  
 
 
альтернатива  
 
Set Range = Range.Find(What:="string", _  
_____________________After:=Range("A1"), _  
_____________________LookIn:=True, _  
_____________________LookAt:=xlWhole, _  
_____________________SearchOrder:=xlByColumns, _  
_____________________SearchDirection:=xlPrevious, _  
_____________________MatchCase:=True, _  
_____________________MatchByte:=True, _  
_____________________SearchFormat:=Null)  
 
здесь, пожалуй, только парсинг :=  
 
Следует отметить, что VBA, на мой взгляд, не очень удобен в этом отношении из-за := и _  
Например в javascript, можно было бы записать так:  
 
Set Range = Range.Find({What: "string",    
______________________After: Range("A1"),    
______________________LookIn: True,    
______________________LookAt: xlWhole,    
______________________SearchOrder: xlByColumns,    
______________________SearchDirection: xlPrevious,    
______________________MatchCase: True,    
______________________MatchByte: True,    
______________________SearchFormat: Null})  
 
все пракрасно видно и ничего не мазолит глаза
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
не-а. :)  
 
речь именно о "удобно/неудобно" - ессно, в приложении к каждому конкретному человеку, коду и ситуации.  
и "удобно/неудобно" здесь я понимаю достаточно широко:  
- у/ну кодить - время, кол-во буковок и т.п. (см. также ппс ниже);  
- у/ну вспомнить самому через некоторое время - разобраться с логикой, внести изменения или исправления логич. ошибок и т.п.;  
- у/ну просматривать код - он в меру компактный или необоснованно размазан?;  
- у/ну передать кому-либо или сохранить всерьез и надолго - в личную книгу или надстройку...;  
- etc.  
 
другое дело - если работать в команде и придерживаться определенных стандартов ЭТОЙ команды. мы ж не об этом?  
 
а так - в пределах разумного - пожалуйста, пишите как УДОБНО вам.  
вот только не надо говорить, что это - "правильно", а чуть иначе - "неправильно".  
а впрочем... можно и говорить - я всё равно не поверю :)  
 
пс.  
пример с    
Set Range = Range.Find("string", Range("A1"), True, xlWhole, xlByColumns, xlPrevious, True, True, Null)    
хорош, но я такого и не предлагал :)  
 
ппс. С.М., по п.3 - неужели  
Dim i As Integer, j As Integer, k As Integer, A(1 To 100) As Integer  
 
или (ещё круче:)  
Dim i As Integer  
Dim j As Integer  
Dim k As Integer  
Dim A(1 To 100) As Integer  
 
лучше чем  
Dim i%, j%, k%, a%(1 to 100)  
 
???  
(я уж молчу про затраты времени, но - хотя бы результат?..)
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
{quote}{login=ikki}{date=27.05.2012 06:00}{thema=nerv, С.М. - приветы}{post}неужели  
Dim i As Integer, j As Integer, k As Integer, A(1 To 100) As Integer  
 
или (ещё круче:)  
Dim i As Integer  
Dim j As Integer  
Dim k As Integer  
Dim A(1 To 100) As Integer  
 
лучше чем  
Dim i%, j%, k%, a%(1 to 100)  
 
???  
(я уж молчу про затраты времени, но - хотя бы результат?..){/post}{/quote}  
Саша,  
1. я оговорил: ИМХО.  
2. "про затраты времени":  
пишу строку  
Dim I, J, K, A(1 To 100) As Integer  
копирую  " As Integer" и всталяю после каждого  I, J, K
 
Друзья,многофбукофф и если я правильно понимаю, не по моей теме) я так и не получил на ответ на свой последний вопрос, про проверку на совпадения. Я не понимаю,какие действия и какие команды нужны, просьба, написать в подробностях и понятно)
 
А Вы повторите еще раз вопрос, и опишите задачу более подробно. Счас все скучают - минут через 5-10 получите кучу вариантов.  
 
зы. Я думал свой вариант сделать, но не понял, что Вы там делаете вообще (т.е., что нужно получить на выходе)
 
эм...ну смотрите,я делаю тест) и случайным образом выбираю из списка элементов 20 штук. И они НЕ должны повторяться. То есть в столбике не должно быть повторений
 
1.  
With CreateObject("Scripting.Dictionary")  
   For Each aa In a  
      .Item(aa) = 1  
   Next  
   If .Count < UBound(a) Then MsgBox "В выбранном диапазоне имеются дубликаты!"  
End With  
2. A зачем    
ReDim Preserve a(1 To i, 1 To 5) ?  
размерность массива известна  
For i = 2 To 21    
и пишите просто  
Dim a(1 To 20, 1 To 5)
 
option base 1  
sub t()  
 dim c as new collection, i%, a%(100), b%(20), x%  
 for i = 1 to 100  
   c.add i    
 next  
 randomize  
 for i=1 to 20  
   x = rnd * (n - i) + 1  
   b(i) = a(c.item(x))  
   c.remove x  
 next  
end sub
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
Страницы: 1 2 След.
Читают тему
Наверх