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

» Excel VBA (часть 3)

Автор: AndVGri
Дата сообщения: 10.02.2011 05:26
Kiljes

Цитата:
тут вдруг это значение повторяется и нужно, чтобы этот повтор как-то отобразился

Так, а чем предложенная процедура не устраивает?

Цитата:
числа 810 и 968 обозначают значИния строк

Ну, а в чём проблема? Определяешь последнюю строку как

Код:
Dim LastRow As Long
LastRow = ActiveSheet.UsedRange.Rows.Count + ActiveSheet.UsedRange.Row - 1
Автор: jvg
Дата сообщения: 10.02.2011 10:34
Добрый день, уважаемое сообщество !

Обращаюсь к вам за посильной помощью в решении рабочей задачи. Суть вопроса заключается в наличии некоего .xls файла с перечнем артикулов продукции, ценой, остатком на складах и примитивными групповыми операциями с данными (итоговое кол-во). Артикулы сгруппированы по категориям на отдельных закладках.
Суть задачи состоит в том, чтобы прикрутить к артикулу в свойства ячейки линк на фото, которые находятся в отдельном каталоге. Есть текстовый файл с полными путями к фото, сгенерированный батником. Пути к фото и ячейки с артикулами, соответственно, имеют
один общий признак-уникальное наименование артикула.
Руками месить около 30000 наименований совсем грустно, времени на это просто нет.
Таких файлов 3 штуки, обрабатываются они с помощью макроса, который заполняет данные по остаткам и продажам за день на основании выгрузки из 1С.
Может быть есть вариант перепаять существующий макрос для задачи под фото ?

Автор: ZlydenGL
Дата сообщения: 10.02.2011 15:09
Да легко! И любой VBA'шник, знающий про Hyperlinks.Add, это легко сделает Пример файлов и путей расположения можно в студию?
Автор: jvg
Дата сообщения: 10.02.2011 15:57
ZlydenGL, файлы тут.
Автор: Zloy_Gelud
Дата сообщения: 11.02.2011 14:10
При попытке посчитать такую формулу

Код: Z = Zp2 * N2 + (Zp2 - Zp1) * ((Zp1 * N1 - Zp2 * N2) / (Zp2 - Zp1))
Автор: asbo
Дата сообщения: 11.02.2011 14:59
Zloy_Gelud
Надо явно преобразовывать результаты промежуточных вычислений в лонг CLng()
Надо было кнопку Help [more=нажать]

You attempt to use a number in a calculation, and that number is coerced into an integer, but the result is larger than an integer. For example:
Dim x As Long
x = 2000 * 365 ' Error: Overflow
To work around this situation, type the number, like this:

Dim x As Long
x = CLng(2000) * 365[/more] :)
Автор: Zloy_Gelud
Дата сообщения: 11.02.2011 15:26
asbo

Цитата:
Надо было кнопку Help нажать

Нажимал то я. Тока так и не понял что он от меня хочет..
Автор: asbo
Дата сообщения: 11.02.2011 15:39
Zloy_Gelud
Ну, для начала, можно (и нужно) сократить до:

Код: Z = Zp1 * N1
Автор: Zloy_Gelud
Дата сообщения: 11.02.2011 15:58
asbo

Код: tmp1 = CLng((Zp2 * N2))
tmp2 = CLng((Zp2 - Zp1))
tmp3 = CLng((Zp1 * N1))
tmp4 = CLng((Zp2 * N2))
tmp5 = CLng((Zp2 - Zp1))

Z = tmp1 + tmp2 * CLng(tmp3 - tmp4) / tmp5
Автор: asbo
Дата сообщения: 11.02.2011 16:34
Zloy_Gelud, CLng() за скобки нельзя выносить :))

Код: tmp1 = CLng(Zp2) * CLng(N2)
tmp2 = Zp2 - Zp1
tmp3 = CLng(Zp1) * CLng(N1)
tmp4 = CLng(Zp2) * CLng(N2)
tmp5 = Zp2 - Zp1

Z = tmp1 + tmp2 * ((tmp3 - tmp4) / tmp5 )
Автор: Zloy_Gelud
Дата сообщения: 11.02.2011 16:40
asbo -- поможешь исправить?
Автор: asbo
Дата сообщения: 11.02.2011 17:00
Zloy_Gelud
Дык, можно посмотреть. Давай материал в личку - файл xls (2003 и до него) сархивируй с паролем, выложи куда-нибудь, пароль мне в личку. Надо взглянуть, вопросы потом задам. Скайп, если есть - сообщи. Но, имей ввиду, - в VBA функции округления корректной (школьной) нету... Придется раком делать. Если нужно быстродействие - нужна библиотека будет.
Автор: Zloy_Gelud
Дата сообщения: 11.02.2011 19:41
asbo
Проблема разрешилась. Дело даже было и не в формуле. Она и в первоночальном варианте работала.
Возник другой вопрос. Допустим, в ячейке записано какое-нибудь десятичное число (12,5; 0,4; 1,5 и т.д.). Необходимо проверить входит ли это число в интервал от 3 до 14. Нужно ли это десятичное число предварительно как-нибудь конвертировать перед проверкой? Или достаточно будет такого?

Код: Cena = Cells(N, 6).Value
If Cena > 3 And Cena <= 14 Then
'...
End If
Автор: asbo
Дата сообщения: 11.02.2011 20:27
Zloy_Gelud
Если бы ты не спросил, я бы так и написал :)
А вот задумался... Я же не спец, боюсь я операций сравнения (на равенство) даблов. Тут, вроде бы, все чисто, но, чтобы перебдеть:
If (Cena > 3) And (Not Cena > 14) Then

* Дело даже было и не в формуле. Она и в первоночальном варианте работала
Смотри... Дело хозяйское... Это же цены, зарплаты, НДС... Я, обычно, радуюсь, когда такие шняги вылазят. Дело в том, что тут у тебя явный косяк будет с округлением при дробном N2, если tmp1 целое:
tmp1 = Zp2 * N2
Хоть с CLng(), хоть без него. Все равно надо явно приводить и правильно (!) округлять. Правильно, значит так как надо твоему главбуху: по школьному, по банковски, как-то еще...
Автор: dneprcomp
Дата сообщения: 11.02.2011 21:49
asbo
Если работа идет с деньгами, то и выбирать наверное лучше Currency Data Type
Тогда и округления будут с достаточной для денег точностью.
Если надо большая точность, то берем Decimal Data Type
В Long хранятcя только целые числа.
VBA Data Types


Zloy_Gelud

Цитата:
If (Cena > 3) And (Not Cena > 14) Then

А смысел делать двойное boolean сравнение?

Код If Cena > 3 And Cena <= 14 Then и так работат нормально. Главное объявить Cena с правильным Data Type, чтобы не сравнивать дробные с целыми. Вроде бы должно и так
пройти сравнение нормально(дробнoе с целым), но я бы подстраховался.
Автор: asbo
Дата сообщения: 11.02.2011 22:15
dneprcomp

Цитата:
Если работа идет с деньгами, то и выбирать наверное лучше Currency Data Type
Тогда и округления будут с достаточной для денег точностью.
Если надо большая точность, то берем Decimal Data Type

Немного не об этом идет речь. Не о точночти, а об округлении. О том, что как и явное , так и неявное приведение к целому округляет (частный случай, до нуля) "неправильно". Для бухгалтерии именно _это_ неприемлемо, а не низкая или высокая точность.

Касательно Currency, то я их руками не трогал и порекомендовать или наоборот не могу. Это же некое scaled int. Наверное, кроме привлекательного названия есть свои нюансы и подводные камни в его использовании.

* В Long хранятcя только целые числа
Благодарю. Чем обязан столь важному напоминанию?

* А смысел делать двойное boolean сравнение?
Я выше объяснял - для того, чтобы избежать сравнения на равенство двух, одно из которых дробное. Объяснил, также, что это перестраховка. Не уверен, но только два дабла нельзя сравнивать на равенство. С целым, вроде бы, можно.

* Главное объявить Cena с правильным Data Type
Я к этому и клонил, но там, похоже, надо сверху начинать. С Option Explicit :)
Автор: dneprcomp
Дата сообщения: 12.02.2011 04:22
asbo

Цитата:
* В Long хранятcя только целые числа
Благодарю. Чем обязан столь важному напоминанию?

К тому, что округлять дробные числа до целых в деньгах как-то не принято. Это самое округление и проводится с разной точностью в зависимости от data type.
Естественно, бухгалтерии не нравится, что 0.45 округляется до 0.00 при помещении в long. В денежных расчетах используют округление с точностью до 3-4 знаков после запятой. Им имено точность расчета и не нравиться.

Цитата:
Это же некое scaled int.

Currency это как бы вариант decimal с точностью до 3 или 4(не помню сейчас точно) знаков после запятой.
Цитата:
Для бухгалтерии именно _это_ неприемлемо, а не низкая или высокая точность.

Непонятно, каким образом делая денежные расчеты, вас не интересует точность расчета.
Опасаетесь currency, возьмите decimal. Но long здесь совершенно не к месту. Из-за не правильного data type у вас и округление идет неверное.

Цитата:
Я выше объяснял - для того, чтобы избежать сравнения на равенство двух, одно из которых дробное

And (Not Cena > 14) выдаст такой же результат как и And Cena <= 14 , но при зтом будет выпонено в 2 раза больше boolean операций. При одноразовом расчете просто ненужная мелочь. При расчете в цикле - дополнительное время. В целом, просто никому не нyжная операция, т.к. все равно в любом случае сравниваете дробное с целым.
Автор: asbo
Дата сообщения: 12.02.2011 11:51
Друже, не ешьте на ночь сырых помидор. Ну почему ближе к выходным и в течение их у дедов руборда крышу рвет?

* В Long хранятcя только целые числа
- Благодарю. Чем обязан столь важному напоминанию?
* К тому, что округлять дробные числа до целых в деньгах как-то не принято.

А в Киеве дядька... хочется продолжить. Я спрашивал чем я обязан тому, что Вы меня носом тыкаете в азбучные истины. И потом, у кого не принято? У Вас? А у меня принято. Мы просто разные суммы считаем. Еще раз повторю - _я_ ничего еще не округляю и не считаю :)

* Это самое округление и проводится с разной точностью в зависимости от data type.
Вы сами-то вслух читаете, то, что пишете? При чем здесь data type? Друже, научитесь отличать точность округления и точность, с которой хранится число. Что Вы на слово "точность" делаете стойку, тем более, вне контеста его использования, а потом еще и сами контексты перемешиваете?

* Непонятно, каким образом делая денежные расчеты, вас не интересует точность расчета.
Снова повторю - не я делаю, а Zloy_Gelud. Денежные - это Ваша фантазия (сырые помидоры ?) и мое скромное предположение, на котором я, в отличие от Вас, не настаиваю с такой завидной упертостью.

* Опасаетесь currency, возьмите decimal.
Ага. Не нравится красную, зае..ньте зеленую.
Я писал, что я "опасаюсь"? Нет. Я писал, что "... порекомендовать или наоборот не могу." С чего Вы решили, что я вообще нуждаюсь в той или другой? Еще раз напомню - я отвечал на вопросы Zloy_Gelud.

Если все таки отвлечься на currency и decimal, то, как же Вы можете рекомендовать то или другое, если Вы даже определения currency не знаете?! Вот я и предостерег Zloy_Gelud своим намеком.

* Но long здесь совершенно не к месту.
Во-первых, где "здесь"? Вы уж потрудитесь среди нескольких переменных и двух строчек кода указать поточнее - какое "здесь" имеется ввиду.
А во-вторых, это дело хозяйское, какой дататип использовать. Я указал Zloy_Gelud на ошибки, несоответствия и возможные траблы? Указал. Он принял к сведению. Хозяин-барин, решит сам. На меня-то что Вы набросились со своими нравоучениями?

* Из-за не правильного data type у вас и округление идет неверное.
Опять за рыбу деньги... How much the fish? У меня нет никакого округления! Где Вы его увидели?! Ткните пальцем. Тем более "Из-за не правильного data type". Повторюсь, - читайте вслух то, что пишете. Даже если предположить, что будет "правильный" тип, что правильного, согласно Ваши рекомендациям, появится в тех неявных округлениях, которые присутствуют в этом коде?! Читайте, друже, читайте внимательно тему. Вот, что я писал: "... тут у тебя явный косяк будет с округлением ... Все равно надо явно приводить и правильно (!) округлять. Правильно, значит так как надо твоему главбуху..."

* And (Not Cena > 14) выдаст такой же результат как и And Cena <= 14
Читайте тему. Внимательно читайте. И не вырывайте из контекста.
Вот мои слова: "...вроде бы, все чисто, но, чтобы перебдеть: If (Cena > 3) And (Not Cena > 14) Then "

* ...все равно в любом случае сравниваете дробное с целым...
Но ужЕ не на равенство! И исключительно с целью "перебдеть".

* В целом, просто никому не нyжная операция,
Никому... Вы, уже сединами убеленный мембер, с регалиями... Вас еще жизнь не научила не впрягаться за весь инет? Хотя, если Вы красным так вот запросто пишете...
Вы уже не помните, что ее избыточность я констатировал и аргументировал в момент ее предложения? Милый мой КО... :)

А если [more=серьезно], ответьте, плз, авторитетно и ответственно - даете фал на пятаки, что "выдаст такой же результат"? Бабками ответите? Впрочем, при Вашей некомпетентности и безаппеляционности суждений и рекомендаций я не удивлюсь, что Вы ответите "Да" :))

Поизучайте на досуге:

Цитата:
При сравнении значения типа Single со значением типа Double, значение типа Double округляется до точности типа Single. Если значение типа Currency сравнивается со значением типа Single или Double, то значение типа Single или Double преобразуется к типу Currency. Аналогично, при сравнении значения типа Decimal со значением типа Single или Double, значение типа Single или Double преобразуется к типу Decimal. Для типа Currency любая дробная часть со значением, меньшим 0,0001 может оказаться потерянной. Для типа Decimal могут быть потеряны дробные части, меньшие 1E-28, или возникнуть ошибка переполнения. Потеря дробных частей может привести к тому, что числа, не являющиеся целыми, будут сравниваться как целые.
[/more]

* будет выпонено в 2 раза больше boolean операций. При одноразовом расчете просто ненужная мелочь. При расчете в цикле - дополнительное время.
Тут Вы меня ужЕ определенно [more=достали]. Вам поумничать захотелось? Похоже на то. Покуражившись над currency, decimal и округлением, Вы решили, что Вам и этого мало. Взялись за оптимизацию кода? Тем более на ровном месте - ведь было оговорено, что лишняя операция предпринимается сознательно и именно "чтобы перебдеть". Более того, еще выше я писал про округление "Если нужно быстродействие..." Я имею его, быстродействие, ввиду, имею...

Нет же, Вы все равно всунулись... Что ж. Назовите цифру. На сколько? Назовите мне задачу, где бы это было критично. Какие объемы данных гнадо при этом проворачивать? А? Может и назовете, только вот к вопросу Zloy_Gelud это можно будет привязать только в Вашем больном воображении. А, бзв, подскажу, что я именно такие объемы и ворочаю, считаю каждую операцию.

Вот, взгляните. Мсек - отсчет по GetTickCount, Микросек - отсчет по HRT.

Так вот. Разница даже еще не в полсекунды (!), а 0,373 сек возникнет только на 100-миллионном цикле. А на цикле в 1 млрд разница составит 4 сек (и то - без копеек)[/more]

И, [more=последнее:]
* Currency это как бы вариант decimal с точностью до 3 или 4(не помню сейчас точно) знаков после запятой.
Пацталом... Вы вначале разберитесь со своим "как бы" и "не помню", а потом уж пытайтесь давать рекомендации и нравоучения. Я выше уже вежливо Вам намекал и обращал внимание на возможные нюансы использования этого типа. Вместо отсылания людей на левые ссылки типа VBA Data Types, обратитесь лучше к первоисточникам:

Цитата:
Currency Data Type

Currency variables are stored as 64-bit (8-byte) numbers in an integer format, scaled by 10,000 to give a fixed-point number with 15 digits to the left of the decimal point and 4 digits to the right. This representation provides a range of -922,337,203,685,477.5808 to 922,337,203,685,477.5807. The type-declaration character for Currency is the at sign (@).

The Currency data type is useful for calculations involving money and for fixed-point calculations in which accuracy is particularly important.
[/more]
Автор: dneprcomp
Дата сообщения: 12.02.2011 18:34
asbo
Извините, просто перепутал кто изначально спрашивал.
Автор: asbo
Дата сообщения: 12.02.2011 19:52
dneprcomp
Да ладно, проехали :) А я столько старался, писал, аргументировал :)
Автор: DmitryPrint
Дата сообщения: 13.02.2011 01:43
asbo

Цитата:
Не уверен, но только два дабла нельзя сравнивать на равенство.

Я выкручиваюсь следующим образом:
Код: Dim h1_ As Double, h2_ As Double

If Round((h2_ - h1_), 8) = 180# Then
Автор: asbo
Дата сообщения: 13.02.2011 11:41
DmitryPrint

Цитата:
...совпадает с такими же расчетами на рабочем листе

В твоем коде тоже есть подводные камени. Вот первый:

попробуй в Immediate Window (Ctrl+G) '? Round(9.65, 1)' и на листе '=ОКРУГЛ(A1,1)' (в A1 занеси 9.65). А потом, для интересу, возьми 9.55 :)

Надо менять... Я где-то выше писал, что выбор алгоритма округления - отвественное место.
Автор: DmitryPrint
Дата сообщения: 14.02.2011 00:54
asbo
Цитата:
В твоем коде тоже есть подводные камени.
Я знаю, но речь шла о "сравнивать на равенство". Без Round, когда результат равен 180.0000000000...0 вычисления идут по неправильному пути (не помню только сейчас результат сравнения то ли считается что больше то ли меньше). С Round все отрабатывается как положено и при равенстве значений все в порядке.
Т.о. в ряде случаев вполне себе выход, если знать все ограничения.
Автор: asbo
Дата сообщения: 14.02.2011 08:13
DmitryPrint, да, речь шла о "сравнивать на равенство". Но, аргументом к приведенному коду (он может быть вполне годным в данном конкретном случае), прозвучало:
Цитата:
... результат расчетов на VBA ...совпадает с такими же расчетами на рабочем листе...
Функция округления листа округляет иначе, чем VBA Round. Как же тогда можно сравнивать результаты их работы? Для этого я и привел пример.

Я давно ушел от работы с даблами - задача позволила, поэтому сходу не смогу предложить алгоритм, но в рунете, по памяти, море материалов на эту тему.
Автор: KolyaP
Дата сообщения: 16.02.2011 22:40
Есть такой метод
Application.Dialogs(xlDialogOpen).Show, он вызывает диалоговое окно открытия файла.

А можно ли решить задачу: вызвать подобный диалог с програмно установленной маской отображения файлов, чтобы диалог возвращал путь выбранной папки?
Автор: AndVGri
Дата сообщения: 17.02.2011 01:50
KolyaP

Цитата:
чтобы диалог возвращал путь выбранной папки?


Код:
Application.FileDialog(msoFileDialogFolderPicker).Show
Автор: asbo
Дата сообщения: 17.02.2011 08:45
KolyaP
Dialogs - "A collection of all the Dialog objects in Microsoft Excel. Each Dialog object represents a built-in dialog box" Это коллекция встроенных диалогов. Есть ли среди них возвращающий имя папки? Не знаю. Вообще-то метов Show возвращает True или False.

Насчет масок - взгляни "Built-in Dialog Box Argument Lists" Может там и есть какие-то модификаторы...
Автор: KF121
Дата сообщения: 17.02.2011 11:09
Подскажите как программно(автоматически) проверить проект на наличе ошибок синстаксических, как это делает через кнопку "Debug->Compile VBA Project"?
Автор: KolyaP
Дата сообщения: 17.02.2011 17:31
Есть такой метод
Application.Dialogs(xlDialogOpen).Show, он вызывает диалоговое окно открытия файла.

А можно ли решить задачу: вызвать подобный диалог с програмно установленной маской отображения файлов, чтобы диалог возвращал путь выбранной папки?
Автор: mrdime
Дата сообщения: 17.02.2011 17:39
KolyaP
Ты что думаешь, если будешь несколько раз повторять свой вопрос на одной странице на него быстрее ответят?

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127

Предыдущая тема: VS 2010


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