Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Excel VBA (часть 3)

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

Открыть новую тему     Написать ответ в эту тему

ShIvADeSt



Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

 
 
Обсуждаем вопросы только по Excel VBA
(программирование макросов, скриптов, пользовательских функций и т.п.).
Приветствуются ссылки на ресурсы и справочную литературу по теме.
 
Вопросы по работе с MS Excel, не относящиеся к программированию, задаем в теме Excel FAQ

 
Обратите внимание, этот топик для помощи в изучении и использовании VBA. Посему запросы типа "Напишите мне такой-то макрос, я VBA не знаю и знать не хочу" не приветствуются.
Древняя мудрость: "Накорми голодного рыбой и он погибнет, научи его ловить рыбу и ты спасешь его."(R)
 
Предыдущие ветки топика: Часть 1, Часть 2
 
Информация общего характера:
  • Список соответствия имен функций в английской и русской версиях Excel
  • Описание Microsoft Excel File Format (eng.)
     
    Рекомендации:
    Если у Вас есть проблема, не решаемая стандартными средствами Excel (об этом можно уточнить здесь) или требующая автоматизации, попробуйте для начала записать макрос самим Excel через меню Сервис (Tools) - Макрос (Macro) - Начать запись (Record New Macro). Подробнее здесь. В большинстве случаев получившийся код (Сервис-Макрос-Макросы-Изменить) Вас не удовлетворит, но подскажет, какие объекты-методы-свойства использовать.  
    Другой Ваш помощник - Просмотр объектов (Object Browser). Ну и встроення помощь (F1), естественно.
     
    Если Вы в тупике, покажите Ваш код (или часть кода) здесь.  Если вылазит ошибка, цитируйте ее полностью. Если код слишком большой, используйте тeг [more].
    Используйте отладчик - Breakpoints (F9), Watches (Shift-F9), Steps (F8 и др.) Сильно облегчает поиск ошибок.

     
    Рекомендуется к прочтению:
  • Первые шаги с Excel VBA
  • Excel VBA: Приёмы программирования
  • WinApi. Лекция из курса "Основы офисного программирования и язык VBA" (для продвинутых)
  • Daily Dose of Excel (eng.) - тематический блог: советы по работе с Excel и прочие материалы
  • Excel Macros & Excel VBA Code Tips, Tricks (eng.) - советы, трюки и уловки
  • Mr. Excel (forum) (eng.) - весьма оживленный форум по Excel&VBA.
  • Приемы, хитрости, трюки и нюансы работы в Microsoft Excel - сайт "Планета Excel", целиком посвященный Excel и всему, что с ним связано.
  • Microsoft Excel: Таблицы и VBA. Справочник. Вопросы и Ответы. Советы. Примеры.  
     
    Родственные топики:
  • Вопросы по работе с MS Excel - Excel FAQ - часть 1, часть 2, часть 3
  • Технические проблемы с MS Office 2003 или Office XP.
  • Word VBA все вопросы по Word VBA туда
  • Access все вопросы по программированию в Access туда
  • Книжульки по VBA - книги по программированию с использованием VBA
     
    Конкретные вопросы:
    Форма-заставка
    Как запустить макрос при изменении положения курсора или значения ячейки
  • Пример 1
  • Пример 2
  • Пример 3 (проверка области)
  • Пример 4
  • Пример 5
    Зацикливание в функции Change или SelectionChange
     
    Ранжирование без пробелов (макрос включает функции сортировки массива и удаления дубликатов, работает и в Excel 2007)
  • под Office 97
     
    Добавление в главное меню своего пункта, ассоциированного с макросом
    Создание ярлыка на рабочем столе
    Снятие защиты листа при забытом пароле
    Смена раскладки клавиатуры
    Скролл формы колесом прокрутки мыши
    Оптимизация кода по быстродействию использованием массивов
    Найти "чужое" окно и нажать в нем кнопку (вписать текст в текстовое поле)
    Работа с UNICODE-символами в VBA: запись, чтение из ячейки, перевод в ASС и обратно
    Как программно подключить дополнительные библиотеки (например, "Microsoft Scripting Runtime" или "Microsoft ActiveX Data Objects 2.8 Library) через References
     
    Перечень основных ColorIndex'ов из MSDN
     

    Смежные темы:
    Программы » Microsoft Office 2019 & 365 | 2016 | 2013 | 2010 | 2007 | 2003
    Программы » OneNote | Outlook 2013 & 2016 & 2019 | Outlook 2010 | Microsoft Mathematics & Math Solver
    Программы » Word FAQ | Excel FAQ | Access FAQ
    Прикладное программирование » Word VBA | Access VBA  
    Андеграунд » Microsoft Office 2019 | 2016 | 2013 | 2010 | 2007 | 2003
    Андеграунд » OneNote | Visio | SharePoint Server | Project Server | Exchange Server
    Андеграунд » Надстройки (add-ins) и коммерческие макросы Excel
    Андеграунд » Самостоятельная сборка дистрибутивов Оffice 2007/2010/2013/2016 | MUI для Office 2007

  • Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 10:16 11-01-2010 | Исправлено: ALeXkRU, 16:42 03-08-2021
    DmitryPrint

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    del

    Всего записей: 39 | Зарегистр. 05-08-2008 | Отправлено: 20:32 17-03-2011 | Исправлено: DmitryPrint, 21:52 17-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    DmitryPrint :)
    Да нет у нее никаких преимуществ. Другая функция просто. Какие преимущества опреации сложения перед операцией умножения?  
     

    Цитата:
    видит там что-то внутреннее, да и черт с ней

    Ну так и пользуйтесь. Если Вас устраивает результат, ко мне-то какие вопросы? Вы в очередной раз пытаетесь меня втянуть в дискуссию сравнения зеленого с кислым. Увольте...
     
    А касательно условия, но которые Вы ссылаетесь, то (не в обиду никому) было мудро сказано "Ну если б мы им предоставили возможность что-либо решать, то..." :) (Что-то меня на классику пробило. Жизнь такая....)
     
    Я это к тому, что если _буквально_ понимать условия задачи, то лучше уж тогда и не садиться за прграммирование.  
     
    Т.о. вот по этому условию
    Цитата:
    ... удаления пустых строк и столбцов ... т.е. в которых все ячейки - не содержат видимых значений.  
    ... при его формальном выполнении, будут удалено все, что содержит апострофы, пробелы, длинные пробелы, другие служебные символы, как то - конец строки, перевод строки etc. Даже если и есть данные, но с белым цветом шрифта - они будут удалены. Мало того, процесс удаления придется произвести _по_всему_ листу - сколько там в нем строк-столбцов. До физичиских его границ. Я это к тому, что произойдет, если формально подойти к решению поставленной задачи.
     

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 22:15 17-03-2011 | Исправлено: asbo, 22:17 17-03-2011
    DmitryPrint

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

    Цитата:
    если формально подойти к решению поставленной задачи.  
    Ну это уж перебор. И потом VBA все-таки прикладной язык. Если некая задача решена - уже хорошо. Потом можно оптимизировать и улучшать и пр.
     
    Насчет моего примера - да, может и не то поудалять, например формулы, если ссылка идет на пустые ячейки. Или если в ячейке ссылка на ячейку, которая имеет значение Empty.
    Там надо все-таки использовать .Value и сравнивать с "".
    Просто функцией IsEmpty вопрос не решается. Если ячейка как-то модифицировалась, то возвращается "", а не Empty.
     

    Всего записей: 39 | Зарегистр. 05-08-2008 | Отправлено: 23:04 17-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Бля... я устал... Со мной-то что спорить? Я ничего не спрашивал.
     
    * да, может и не то поудалять
    * все-таки использовать .Value и сравнивать с "".  
    * Просто функцией IsEmpty вопрос не решается
     
    Вы хотите и можете порекомендовать вопрошающим что-то конкретное? Форвардс! Вот тогда и обсудим Ваши подходы, мои, еще чьи-нибудь. Вы же ничего не предлагаете конкретного... Преобразуйте Ваши убеждения в код, а не во флуд.
     
    И последнее:
    * Если ячейка как-то модифицировалась, то возвращается "", а не Empty.  
    Кем возвращается? Код в студию.
     

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 23:35 17-03-2011
    DmitryPrint

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

    Цитата:
    Со мной-то что спорить?
    Да бросьте, нафиг оно надо.

    Цитата:
    Кем возвращается? Код в студию.  
    для тестирования брал файл выложенный mrdime, и заново созданный.
     
    на обоих одинаковые результаты выдаются при строке If Range(col & CStr(i)).Value <> "" Then
    если использовать If Not IsEmpty(Range(col & CStr(i))) Then
    то выложенном файле результат неверный, а в заново созданном все в порядке. С выложенным помогает только очистка ячеек.
    (для сравнения с выложенным файлом, просмотр организован только для диапазона A8:A16)
     
    Выходит, что сравнение с "" работает более универсально, чем IsEmpty.
     
    P.S. А в случае, если информация содержит спецсимволы, то мне кажется проще все  
    это безобразие затянуть целиком в vba и обрабатывать в нем, обращаясь к Excel только для вывода результатов.

    Код:
    Option Explicit
     
    Function emptyCol(ByVal col As String) As Boolean
        Dim i As Integer
        For i = 8 To 16
    '        If Not IsEmpty(Range(col & CStr(i))) Then
            If Range(col & CStr(i)).Value <> "" Then
                emptyCol = False
                Exit Function
            End If
        Next i
        emptyCol = True
    End Function
         
    Sub test()
        Dim myCol As String
        myCol = "A"
        If emptyCol(myCol) Then
            MsgBox "column " & CStr(myCol) & " empty"
        Else
            MsgBox "column " & CStr(myCol) & " not empty"
        End If
    End Sub
     

    Всего записей: 39 | Зарегистр. 05-08-2008 | Отправлено: 00:52 18-03-2011 | Исправлено: DmitryPrint, 01:17 18-03-2011
    SAS888

    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    asbo
    От Ваших слов "пахнет" оскорблением... Ну, ладно. Я не обидчивый. Давайте, все-таки, определим, какой метод быстрее. Для того, чтобы однозначно ответить на этот вопрос, предлагаю файл с исходными данными в столбце "A". Задача: с помощью макроса, получить значение первого встречающегося телефонного номера из каждой ячейки столбца "A" и поместить рядом в столбец "B".
    В файл с данными я поместил свое решение этой задачи с применением объекта RegExp.  
    С нетерпением жду Вашего решения, которое (по Вашим, неизвестным науке расчетам) в 3 раза быстрее.

    Всего записей: 398 | Зарегистр. 31-10-2007 | Отправлено: 05:59 18-03-2011 | Исправлено: SAS888, 06:01 18-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    SAS888
    * Давайте, все-таки, определим, какой метод быстрее.
    А - Все уже определено. Меня не волнует, во сколько именно раз мой код быстрее Вашего. Важно то, что  
    1. Я это определил на глаз
    2. Не выдавал это за безапелляционную истину.
    3. Подтвердил свои утверждения отчетами.
    4. Разница на порядок
    5. Третьи библиотеки не используются
    6. Я в сравнении не использовал заведомо более медленный вариант кода своего визави.
    7. Алгоритм и его реализация более понятны конечному пользователю...
    8. ... и, следоваетльно, легче адаптируются под возможные изменившиеся условия
    (Последние два пункта - чисто субъективное имо - это все-таки мой код.)
     
    Бэ - я с Вами буду взаимодействовать только после получения извинений за Вашу... э-э-э..., которую Вы позволили себе при проведении замеров.
     
    Цэ - Если - см п. Бэ, то можно и побеседовать на тему моих "неизвестных науке расчетов". Только странно, как они могут Вас интересовать, если Вы уже дали им такую саркастическую оценку... И, обращаю Ваше внимание, что Вы, несмотря на неоднократные просьбы, так и не привели ни одной цифры из Ваших замеров. Одни слова...
     
    Добавлено:
    DmitryPrint
    Я файл скачал, но кактастрофически не хватает времени взглянуть. Чуть позже, ОК?

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 15:13 18-03-2011
    SAS888

    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    asbo

    Цитата:
    Меня не волнует, во сколько именно раз мой код быстрее Вашего

    Вы не в то порядке употребили местоимения "мой" и "Ваш".

    Цитата:
    Бэ - я с Вами буду взаимодействовать только после получения извинений за Вашу... э-э-э..., которую Вы позволили себе при проведении замеров.  
    Все Ваши 8 пунктов ничего не стоят, пока Вы не утрете мне нос и представите решение предложенного примера быстрее, чем мой вариант (может быть и в 3 раза, кто Вас знает?), тогда получите мои извинения. В противном случае, извиниться должны Вы.  Жду...

    Всего записей: 398 | Зарегистр. 31-10-2007 | Отправлено: 21:13 18-03-2011 | Исправлено: SAS888, 21:16 18-03-2011
    golkanavt



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Всем привет. Вводная часть  - есть Delphi-проект, в котором посредством Afalina XLReport создается прайс-лист с несколькими именованными листами (sheet). Каким образом можно в данном отчете после его создания добавить в начало книги еще один лист с оглавлением, т.е. чтобы в оглавлении были перечислены все листы со ссылками, т.е. чтобы по клику можно было переходить на нужный лист? В идеале кроме названия листов туда же желательно добавить и структурированное содержимое каждого листа, содержащего цены на те или иные объекты. Заранее спасибо откликнувшимся, готовым помочь в создании - буду благодарен посредством WMZ.

    ----------
    Shit happens...

    Всего записей: 1069 | Зарегистр. 08-04-2002 | Отправлено: 10:10 19-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    w01f14, DmitryPrint, Zloy_Gelud
     
    У меня предложение - давайте забудем об использовании IsEmpty в качестве средства проверки содержимого ячейки на наличие-отсутствие чего-то. Это неправильно.
     
    У меня это IsEmpty появилось в ответе w01f14 "Помогите сделать скрипт который проверит ячейку таблицы на пустоту". Почему я именно его взял? Не знаю. Я сейчас в Access-e плотно сижу, может на автомате написал... Впрочем, я оговорился в следующем же посте, но и меня это не насторожило, увы :( А когда речь зашла об апострофах и прочей нечисти, я уже на автомате посчитал использование IsEmpty за панацею от этих бед. После этого Zloy_Gelud задал вопрос с уже конкретно используемым IsEmpty и понеслось...
     
    Предлагаю обратиться к первоисточникам. Прежде всего, IsEmpty - это VBA-шная функция, не Экселя, т.е. общая для всего Офиса:  
    Function IsEmpty(Expression) As Boolean, Member of VBA.Information
     
    Во-вторых,  

    Цитата:
    IsEmpty(expression) - Returns a Boolean value indicating whether a variable has been initialized.
     
    The required expression argument is a Variant containing a numeric or string expression. However, because IsEmpty is used to determine if individual variables are initialized, the expression argument is most often a single variable name.
     
    Remarks:
    IsEmpty returns True if the variable is uninitialized, or is explicitly set to Empty; otherwise, it returns False. False is always returned if expression contains more than one variable. IsEmpty only returns meaningful information for variants.

    Если кратко, то речь идет о проверке переменной - инициализированна она или нет.
    Подсовывая ей выражение типа Cells(1,1).Value, мы передаем в нее переменную Value (свойство объекта Range) на предмет проверки ее на инициализацию. Не на проверку ее содержимого.
     
    Я уже сокрушался по поводу убогости и скудности английского языка - вот и здесь (я всю тему просмотрел) все отчаянно ведутся на легко переводимое Empty - пустой. Как и я сам :)
     
     
    Касательно апострофа...
     
    Я пока не знаю, что с ним делать. Можно пытаться использовать Cells(1,1).SpecialCells(xlCellTypeConstants).Count
    Но она странно работает с одиночной ячейкой. Надо ей в пару включать в проверяемый диапазон хотя бы еще одну ячейку, в которой заведомо содержится некое "нормальное" значение.  
     

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 12:27 19-03-2011 | Исправлено: asbo, 12:27 19-03-2011
    mrdime



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    В первую очередь адресую это asbo и DmitryPrint, которые заинтересовались моим вопросом насчет создания макроса по поиску и удалению из листа всех пустых строк и колонок.
    Наваял вот такой макрос. Пока использовал проверку лишь на .Value=""
    Пока получилось что-то такое, хотя конечно хотелось бы чтобы удалялись строки и колонки, заполенные пробелами и прочим содержимым, которое пропускает вышеуказанная проверка.
    Хотелось бы услышать ваше мнение по этому поводу/ предложения по оптимизации кода.

    Цитата:
    Sub DelEmptyClmRws()
    'Универсальный макрос для удаления пустых строк и колонок из листа
    Dim R As Integer
    Dim C As Integer
    Dim I As Integer
    Dim CheckCal As Integer
    Dim CheckRaw As Integer
    Dim ContrSum As Integer
    'отменяем объединения ячеек, которые иногда создаются пользователями либо "кривыми" программами
    ActiveSheet.UsedRange.MergeCells = False
    'определям "рабочую зону" нашего листа
    'строчки
        R = ActiveSheet.UsedRange.Rows.Count
    'колонки
        C = ActiveSheet.UsedRange.Columns.Count
    'ищем и удаляем пустые колонки
    'задаем первую колонку, которая будет проверяться
    CheckCol = 1
    Do
        ContrSum = 0
        For I = 1 To R
            If Cells(I, CheckCol).Value <> "" Then
            'вводим контрольную сумму, если попадется хотя бы одна непустая ячейка
                ContrSum = ContrSum + 1
            End If
        Next I
        'если все ячейки пустые, удаляем колонку
        If ContrSum = 0 Then
            Columns(CheckCol).Delete Shift:=xlToLeft
            'уменьшаем "рабочую зону" на единицу
            C = C - 1
        Else: CheckCol = CheckCol + 1
        End If
    Loop While CheckCol < C
    'ищем и удаляем пустые строки
    CheckRaw = 1
    Do
        ContrSum = 0
        For I = 1 To C
            If Cells(CheckRaw, I).Value <> "" Then
            'вводим контрольную сумму, если попадется хотя бы одна непустая ячейка
                ContrSum = ContrSum + 1
            End If
        Next I
        'если все ячейки пустые, удаляем строчку
        If ContrSum = 0 Then
            Rows(CheckRaw).Delete Shift:=xlUp
            'уменьшаем "рабочую зону" на единицу
            R = R - 1
        Else: CheckRaw = CheckRaw + 1
        End If
    Loop While CheckRaw < R
    End Sub


    Всего записей: 2975 | Зарегистр. 04-01-2005 | Отправлено: 12:55 19-03-2011 | Исправлено: mrdime, 12:57 19-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    На вскидку, - прежде всего я бы заменил
    If Cells(I, CheckCol).Value <> ""  
    на
    If Len(Cells(I, CheckCol).Value) > 0  
    Впрочем, с апострофом и это не проканает :) (т.е. ячейки, содержащие один-единственный апостроф тоже будет удалены, но, как я понял из файла , это вполне удовлятворяет)
     
    Потом разделил бы код на четыре части:
    1. Процедура определения рабочего диапазона
    2. Процедура поиска пустых строк
    3. Процедура поиска пустых колонок
    4. Процедура удаления найденного по п.п. 2 и 3
     
    Удобнее было бы и работать, и обсуждать :) И, главное(!) - модифицировать условия включения элементов в удаляемые. А это, скорее всего, понадобится :)

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 14:09 19-03-2011 | Исправлено: asbo, 14:14 19-03-2011
    mrdime



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    asbo

    Цитата:
    прежде всего я бы заменил
    If Cells(I, CheckCol).Value <> ""  
    на
    If Len(Cells(I, CheckCol).Value) > 0  

    Что нам это даст?
    Ячейки с пробелами, например, таким образом все равно проходят проверку.
    Может ты хотел предложить проверку Len(Trim(Cells(I, CheckCol).Value)) > 0? Тогда диапазоны с пробелами улетают как надо.  
    НО не уверен насколько подобная проверка корректна, если в ячейках нестроковые данные. Ведь эта функция предназначена для работы с данными типа "string".

    Цитата:
    Потом разделил бы код на четыре части:  

    Хм... Может я чего-то не понял, но код фактически разделен на 3 части (нахождение рабочего диапазона, поиск пустых колонок, поиск пустых строк). Нет только 4-го пункта, т.е. пустые строки и столбцы удаляются непосредственно во время их нахождения.
    Я думал о таком решении (выделить удаление отдельно). Как вариант можно их удалять не сразу, т.е. номера записывать в двухмерный массив, а потом в отдельной части их по очереди извлекать из массива (отдельно строчки, отдельно - столбцы) и удалять.
    Я не особо силен в многомерных массивах, но попробую ради интереса реализовать.
    В общем, узкую поставленную задачу можно считать решенной. Интересно создание универсального макроса (на все случааи жизни ), который бы кроме того, что уже делает предложенный выше вариант, мог удалять/ очищать строки и колонки со всем возможным мусором типа одинарных скобок  ")", "(", апострофов, одинарных кавычек, неразрывных пробелов, знаков табуляции и т.д.

    Всего записей: 2975 | Зарегистр. 04-01-2005 | Отправлено: 14:41 19-03-2011 | Исправлено: mrdime, 14:55 19-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Бытует мнение, что так грамотнее. Вариант с Len должен работать быстрее, по-идее. Я в циклах именно его использую, а если всего один раз надо сравнить - пофиг, конечно. В первом случае сравниваются строки, вступает в действие стейтмент Options Compare (даже неявно). Просто пробел - частный случай строки с одним символом, как и пустая строка.
     
    * Ячейки с пробелами, например, таким образом все равно проходят проверку.  
    Не понял... Результат идентичен:
    ? " " <> ""  
    True
    ? Len(" ") > 0
    True
     
    Ты же проверяешь на истинность некое утверждение. Я для этого и говорил о разделении кода, чтобы обсуждать его участки, а не ожидаемый конечный результат.
     
    * эта функция предназначена для работы с данными типа "string".
    Цитата:
    Len Function returns a Long containing the number of characters in a string or the number of bytes required to store a variable.

    Даже если говорить о первой части определения, то, я думаю, там используется неявное приведение типов к Str
     
    * номера записывать в двухмерный массив
    Быстрее запутаешься :) Один массив для номеров строк, второй - для номеров колонок. Когда заработает - можно и в двумерный загнать, если особая на то нужда будет. Часто читабельность кода перевешивает плюсы быстродействия и исполнения принятых нотаций написания.
     

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 15:41 19-03-2011 | Исправлено: asbo, 15:42 19-03-2011
    Serzhsv

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Помогите пожалуйста дополнить, исправить или вообще заменить код!
     Нужно чтобы в листе "Отработано" после вставки выделялась следующая свободная строка, указывая место для следующей вставки.
     
    Этот макрос вырезает выделенные строки в листе "NEW Счета", вставляет в выделенную строку (она всегда последняя свободная) в листе "Отработано". Затем в листе "NEW Счета" удаляет освободившиеся после вырезки строки.  
     После его выполнения в листе "Отработано" выделенными остаются последние вставленные строки, а нужно выделить следующую свободную, чтоб не указывать её каждый раз в ручную.
     
    Sub отработано2()
    '
    ' отработано2 Макрос
    ' Макрос записан 28.01.2011 (Менеджер)
    '
     
    '
        Selection.Cut
        Sheets("Отработано").Select
        ActiveSheet.Paste
        Sheets(" NEW Счета").Select
        Selection.Delete Shift:=xlUp
        ActiveCell.Rows("1:1").EntireRow.Select
    End Sub

    Всего записей: 1 | Зарегистр. 19-03-2011 | Отправлено: 16:50 19-03-2011 | Исправлено: Serzhsv, 20:32 19-03-2011
    mrdime



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    asbo
    В общем подшаманил код по твоим рекоммендациям (сделал два простых массива).
    Вот что получилось:

    Цитата:
    Sub DelEmptyClmRws_v2()
    'Универсальный макрос для удаления пустых строк из листа
    Dim R As Integer
    Dim C As Integer
    Dim I As Integer
    Dim Y As Integer
    Dim Z As Integer
    Dim CheckCal As Integer
    Dim CheckRow As Integer
    Dim ContrSum As Integer
    'объявляем массивы с номерами пустых строк и столбцов
    Dim EmptCol(1 To 100) As Integer
    Dim EmptRow(1 To 100) As Integer
     
    'отменяем объединения ячеек, которые иногда создаются пользователями либо "кривыми" программами
    ActiveSheet.UsedRange.MergeCells = False
    '1. определям "рабочую зону" нашего листа
    'строчки
        R = ActiveSheet.UsedRange.Rows.Count
    'колонки
        C = ActiveSheet.UsedRange.Columns.Count
         
    '2. ищем пустые колонки
    'задаем первую колонку, которая будет проверяться
    CheckCol = 1
    Y = 0
    Do
        ContrSum = 0
        For I = 1 To R
            If Len(Cells(I, CheckCol).Value) > 0 Then
            'вводим контрольную сумму, если попадется хотя бы одна непустая ячейка
                ContrSum = ContrSum + 1
            End If
        Next I
        'если все ячейки пустые, записываем номер колонки
        If ContrSum = 0 Then
            Y = Y + 1
            EmptCol(Y) = CheckCol
        End If
        CheckCol = CheckCol + 1
    Loop While CheckCol <= C
     
    '3. ищем пустые строки
    CheckRow = 1
    Z = 0
    Do
        ContrSum = 0
        For I = 1 To C
            If Len(Cells(CheckRow, I).Value) > 0 Then
            'вводим контрольную сумму, если попадется хотя бы одна непустая ячейка
                ContrSum = ContrSum + 1
            End If
        Next I
        'если все ячейки пустые, записываем номер строчки
        If ContrSum = 0 Then
            Z = Z + 1
            EmptRow(Z) = CheckRow
        End If
        CheckRow = CheckRow + 1
    Loop While CheckRow <= R
     
    '4. удаляем пустые строки и колонки
    For I = 1 To Y
        Columns(EmptCol(I)).Delete Shift:=xlToLeft
        EmptCol(I + 1) = EmptCol(I + 1) - I
    Next I
    For I = 1 To Z
        Rows(EmptRow(I)).Delete Shift:=xlUp
        EmptRow(I + 1) = EmptRow(I + 1) - I
    Next I
     
    End Sub
     

    Буду рад советам по расширению функционала по поиску разновсяческих "левых" символов в ячейках (как писал раньше).

    Всего записей: 2975 | Зарегистр. 04-01-2005 | Отправлено: 17:54 19-03-2011 | Исправлено: mrdime, 18:46 19-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    mrdime, я бы процедуру удаления строк поместил перед процедурой поиска колонок - сократится количество ячеек к обработке. Если это приемлемо по логике работы и эргономике, конечно... Сорри, что я последовательно правлю - нет врмени.  
     
    Добавлено:
    Да, чуть не забыл! Удалять сзаду надо начинать!

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 18:37 19-03-2011 | Исправлено: asbo, 20:16 19-03-2011
    mrdime



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    asbo

    Цитата:
    Да, чуть не забыл! Удалять сзаду надо начинать!

    Хорошая идея. Я здорово намучался, пока понял как правильно настроить удаление спереди.
    Учту на будущее.

    Всего записей: 2975 | Зарегистр. 04-01-2005 | Отправлено: 20:49 19-03-2011
    asbo

    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    mrdime, ты меня все-таки разозлил на эту задачу :)) Не хотел я в нее глубоко вникать - нет времени, но, блин ...Смотри:
     
    У-пс. Опечаточки вкрались. Исправил...
     
    Навскидку - логика правильная. Может кто и критикнет с пользой? А то у меня ужЕ глаз замылился...  
    Надо только перед этим удалить подводные камни с листа (очистить ячейки).  
    И я сомневаюсь в корректности .UsedRange, но, в первом приближении - пойдет.
     
    Добавлено:
    Но я, блин, все равно сомневаюсь - хоть и сзаду удаляем, но что там произойдет с диапазонами после удалений... ужЕ кочан не варит ... устал, млин... надо по клеточкам все это дело посмотреть... на свежую голову. Но в качестве рыбы - пойдет. Сам теперь покумекай :)

    Всего записей: 1805 | Зарегистр. 03-10-2006 | Отправлено: 21:24 19-03-2011 | Исправлено: asbo, 21:43 19-03-2011
    DmitryPrint

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

    Цитата:
    но что там произойдет с диапазонами
    В порядке все. Второй раз по одному и тому же не проходит и ничего не пропускает. По лаконичности и компактности удаление здорово сделано.
     
    Я бы, для начала, подрихтовал так:
    Код:
        With rng
            lR_Cnt = .Rows.Count
            lC_Cnt = .Columns.Count
             
            If lR_Cnt <= lC_Cnt Then
                Call sb_DelEmptyRC_Del(.Columns, lC_Cnt, lR_Cnt)
                Call sb_DelEmptyRC_Del(.Rows, lR_Cnt, .Columns.Count)
            Else
                Call sb_DelEmptyRC_Del(.Rows, lR_Cnt, lC_Cnt)
                Call sb_DelEmptyRC_Del(.Columns, lC_Cnt, .Rows.Count)
            End If
            'Если первые пустые, то в .UsedRange они не входят
            'удаляем (если надо конечно)
            Do While (Mid(.Address, 2, 1) <> "A")
                Range("A:A").Delete
            Loop
            Do While (Mid(.Address, 4, 1) <> "1")
                Range("1:1").Delete
            Loop
        End With

    Действия по разметке надо, видимо, попробовать организовать на базе
    str_CellsNeededEmpty = "B7,D11,F7,F13,D16,H13,H5,I7,I11,J13,K7,K11,K16,L15,L5,L3,L1"
    Range(str_CellsNeededEmpty).Value = Empty
    т.е. перебирая ячейки, программно накопить переменную String, которую потом подсунуть в Range. Оценку значений можно попробовать взять готовую из какого-нить макроса для чистки текста перед версткой.

    Всего записей: 39 | Зарегистр. 05-08-2008 | Отправлено: 02:55 20-03-2011 | Исправлено: DmitryPrint, 03:27 20-03-2011
    Открыть новую тему     Написать ответ в эту тему

    Страницы: 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Excel VBA (часть 3)


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru