Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

28 Май 2022, 01:18 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Доступно и просто о работе в офисных пакетах
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1 2 »   Вниз
  Печать  
Автор Тема: Удаление строки с непустыми ячейками в Calc  (Прочитано 1469 раз)
0 Пользователей и 1 Гость смотрят эту тему.
siti
Участник
**
Offline Offline

Сообщений: 47


« Стартовое сообщение: 11 Апрель 2022, 13:43 »

Может быть есть добрые люди которые помогут с макросом. Знания близки к нулю в VB, но срочно понадобилось сделать следующее:
На листе в Calc надо удалить те строки в которых все ячейки в строке не пустые в выделенном пользователем цельном произвольном диапазоне ячеек.
То есть удалять именно строку целиком, а не ячейки из выделения.
В примере на картинке надо удалить строки 12 и 13

Поиском в сети не смог разобраться как работать с выделениями  Грустный


* 2022-04-11_15-41-49.png (2.54 Кб, 633x48 - просмотрено 18 раз.)
« Последнее редактирование: 11 Апрель 2022, 13:46 от siti » Записан
economist
Форумчанин
***
Offline Offline

Сообщений: 1 676


« Ответ #1: 11 Апрель 2022, 14:18 »

1) Напишите с пустом столбце справа формулу, учитывающую пустоту ячеек вида =И(D2="";E2="";F2="")
2) Включите Автофильтр по этому столбцу и оставьте в нем только то, что нужно удалить
3) Выделите удаляемые строки и удалите

Макрорекордер запишет 95% этих действий, вот и макрос...
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
sokol92
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 913


WWW
« Ответ #2: 11 Апрель 2022, 14:29 »

Если выделен прямоугольный диапазон ячеек, то проблемы нет:
Код:
' Удаляет строки выделенного прямоугольного диапазона ячеек
Sub RemoveSelectionRows
  Dim oSel
  oSel=ThisComponent.CurrentSelection
  If oSel.supportsService("com.sun.star.sheet.SheetCellRange") Then
    oSel.SpreadSheet.removeRange oSel.RangeAddress, com.sun.star.sheet.CellDeleteMode.ROWS
  End If 
End Sub
Записан

Владимир.
siti
Участник
**
Offline Offline

Сообщений: 47


« Ответ #3: 11 Апрель 2022, 14:39 »

1) Напишите с пустом столбце справа формулу, учитывающую пустоту ячеек вида =И(D2="";E2="";F2="")
Попробовал. Для фиксированного кол-ва столбцов решение отличное, но если мне надо брать не весь диапазон из формулы, то при удалении лишних столбцов формула ломается. Пишет #ССЫЛ
Мне нужно из 12 столбцов каждый раз выделение из разного кол-во столбцов анализировать на полную занятость в строках выделения и удалять (или разом отфильтровывать) их.
« Последнее редактирование: 11 Апрель 2022, 15:04 от siti » Записан
siti
Участник
**
Offline Offline

Сообщений: 47


« Ответ #4: 11 Апрель 2022, 14:42 »

Если выделен прямоугольный диапазон ячеек, то проблемы нет:
Это просто удаляет строки выделенного диапазона.
Мне нужно удалить строку только если все значения в строке выделения не пустые.
« Последнее редактирование: 11 Апрель 2022, 14:52 от siti » Записан
sokol92
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 913


WWW
« Ответ #5: 11 Апрель 2022, 15:39 »

Прошу прошения, невнимательно прочитал стартовое сообшение. Попробуйте так (RemoveSelectionFullRows):
Код:
Sub RemoveSelectionFullRows() 
  Dim oSel
  oSel=ThisComponent.CurrentSelection
  If oSel.supportsService("com.sun.star.sheet.SheetCellRange") Then
    RemoveRangeFullRows oSel
  End If 
End Sub

' Удаляет (полные) строки прямоугольного диапазона ячеек, если в строке все ячейки не пустые.
Sub RemoveRangeFullRows(ByVal oRange)
  Dim oRange2, arr, v, adr, bDel As Boolean, i As Long, i1 As Long, i2 As Long
  arr=oRange.DataArray
  i2=-1
 
  For i=Ubound(arr) To 0 Step -1 ' строки удаляем снизу вверх
    bDel=True
    For Each v In arr(i)
      If v="" Then
        bDel=False
        Exit For
      End If 
    Next v
   
    If  bDel Then ' i-я строка диапазона должна быть удалена. Запоминаем.
      If i2=-1 Then i2=i
      i1=i
    Else
      If i2>=0 Then
        oRange2=oRange.getCellRangeByPosition(0, i1, 0, i2)
        oRAnge2.SpreadSheet.removeRange oRange2.RangeAddress, com.sun.star.sheet.CellDeleteMode.ROWS         
        i2=-1
      End If 
    End If 
  Next i
   
  If i2>=0 Then
    oRange2=oRange.getCellRangeByPosition(0, i1, 0, i2)
    oRAnge2.SpreadSheet.removeRange oRange2.RangeAddress, com.sun.star.sheet.CellDeleteMode.ROWS
  End If 
   
End Sub 
Записан

Владимир.
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 1 088


« Ответ #6: 11 Апрель 2022, 17:30 »

Возможен другой алгоритм решения этой задачи.
1. Вы выделяете требуемый диапазон.
2. Макрос получает пустые ячейки в выделенном диапазоне. Здесь неважно, если в строке может быть более одной пустой ячейки.
Предполагается, что удобно выделять столбцы целиком. Поэтому ниже используется уже ставшая стандартной пользовательская функция UsedArea().
   oSheet = ThisComponent.CurrentController.ActiveSheet
   oUsedArea = UsedArea(oSheet)
   oRanges = ThisComponent.CurrentSelection _
    .queryIntersection(oUsedArea.RangeAddress).queryEmptyCells()
3. Макрос удаляет те строки, в которые не попали пустые ячейки.
Цикл снизу вверх, как у @sokol92, но с проверкой индекса удаляемой строки.

Edit 1:
С другой стороны, полезно писать процедуры, которыми вы сможете воспользоваться в дальнейшем.
Тогда эту задачу можно разбить на 3 действия:
Выберите диапазон.
Макросы:
1. Выделить пустые ячейки в выбранном пользователем диапазоне (SelectEmptyCells).
2. Распространить выделение ячейки (ячеек в одной строке) диапазона на всю строку (SelectEntireRows).
3. Инвертировать выделение (InvertSelection(Reference As Object), где Reference - это объект Range(s), в котором что-то да выделено).
На экране будет то, что вы могли бы получить, работая вручную.
Самостоятельно удалите выделенные строки.

При таком подходе у вас будет что-то оставаться для использования в будущем. Пишите полезными блоками.
В частности, выделение пустых ячеек в выделенном диапазоне - это полезная процедура, и у меня (и не только) она давно написана. Потому что она есть в Excel и нужна в Calc. Стало быть, в Вашей задаче для меня интерес представляет инверсия выделения (как в окне Автофильтра): это может пригодиться.

Дальше – в зависимости от вашей заинтересованности. @sokol92 в принципе решил вашу задачу.


Edit 2: OFF TOPIC : Кто-нибудь уже реализовал это? Поделитесь...

Что в LO BASIC есть из функций для работы с множествами (диапазонами), кроме пересечения? В Python есть всё.
Объединение, разность, симметричная разность?..

[Union] = rgA + rgB
[Union] = oRanges.addRangeAddresses(Array(rgA.RangeAddress, rgB.RangeAddress), bMergeRanges:=True)  'Может так?

[Difference] = rgA - rgB
[Difference] = oRanges.removeRangeAddress(rgB.RangeAddress)  'И так?

[SymmetricDifference] = Union(rgA, rgB) - Intersect(rgA, rgB)

И тогда для решения задачи автора мы бы вычли из исходного (выделенного пользователем) диапазона те строки, что содержат пустые ячейки, и полученную разницу снова выделили бы. Это и есть результат. Проблемка с "вычитанием". Есть готовая реализация? То, что выше, я не пробовал...
Но если "загнать-добавить" весь исходный диапазон в объект oRanges и "вычесть-удалить" из него выделенные строки (не целые, а в пределах выделенного исходного диапазона), то теоретически мы получим результат, который надо выделить снова и удалить. Или не получим... Мысли вслух.
« Последнее редактирование: 12 Апрель 2022, 09:08 от eeigor » Записан

Ubuntu 18.04 LTS • LibreOffice 7.3.2.2 Community
siti
Участник
**
Offline Offline

Сообщений: 47


« Ответ #7: 12 Апрель 2022, 09:26 »

Всем огромное спасибо.
Метод sokol92 подошел мне максимально, плюс он позволил мне добавить еще одно условие по содержанию другого ключа в ячейке, помимо пусто/не пусто.
Записан
siti
Участник
**
Offline Offline

Сообщений: 47


« Ответ #8: 11 Май 2022, 10:50 »

Прошу прошения, невнимательно прочитал стартовое сообшение. Попробуйте так (RemoveSelectionFullRows):
Код:
А в этом методе возможно получить адрес анализируемой ячейки v In arr(i) не прибегая к переменным счетчикам (i)?
Использую данную процедуру для анализа содержимого выделения и хочу выделять цветом определенные ячейки.
Если приблизить к теме топика то, например выделить цветом не пустую ячейку.
Записан
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 1 088


« Ответ #9: 11 Май 2022, 11:46 »

А в этом методе возможно получить адрес анализируемой ячейки v In arr(i) не прибегая к переменным счетчикам (i)?
Вы ведь перебираете построчно (i - индекс строки)...
Чтобы получить ссылку на ячейку, нужен ещё индекс столбца j. Тогда: oCell = oSheet.getCellByPosition(j, i)

А вообще, много воды утекло с тех пор, и была реализована тема.
В вашем распоряжении следующие процедуры:
Intersection(), Union(), Difference(), SymmetricDifference(), GetCellCollection(), InvertSelection

Теперь можно пойти другим путем:
1. Выделить пустые ячейки в выбранном пользователем диапазоне (SelectEmptyCells). Для этого надо получить диапазоны, содержащие пустые ячейки, и выделить их. Есть 2 метода: oRanges = oRange.getEmptyCells(), ThisComponent.CurrentController.select(oRanges).
2. Распространить выделение ячейки (ячеек в одной строке) диапазона на всю строку (SelectEntireRows). Тоже не сложно (свойство Rows, метод getRows).
3. Инвертировать выделение (InvertSelection). Готовая процедура: вызывает Difference(), а последняя использует GetCellCollection().

А функция GetCellCollection вернёт именно ячейки со всеми их свойствами.

Edit:
Может, перепишем макрос, и заодно протестируем этот набор "инструментов"? Но, похоже, Вам следует уточнить условия задачи...
« Последнее редактирование: 11 Май 2022, 12:28 от eeigor » Записан

Ubuntu 18.04 LTS • LibreOffice 7.3.2.2 Community
siti
Участник
**
Offline Offline

Сообщений: 47


« Ответ #10: 11 Май 2022, 12:05 »

Вы ведь перебираете построчно (i - индекс строки)...
Чтобы получить ссылку на ячейку, нужен ещё индекс столбца.
в принципе да, я уже тоже догадался добавить i3 (условно).
Вопрос снимается, как глупый.

В вашей реализованной теме мне кажется немного не то, что мне требуется. Я уже анализирую текст содержимого ячейки в цикле, а не просто пусто/занято. И надо выделить ячейку при определенном условии.
Записан
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 1 088


« Ответ #11: 11 Май 2022, 12:12 »

Да, но функция GetCellCollection позволяет работать с ячейками без всяких индексов в инвертированном диапазоне.
Код:
For Each oCell In оCellCollection
    MsgBox oCell.String  'oCell.AbsoluteName
    If oCell.String Like "*abc*" Then
        ThisComponent.CurrentController.select(oCell)  'contains "abc"
        Exit For
    End If
Next

Ячейки, отвечающие условию, надо добавить в объект диапазонов (addRangeAddress) поячеечно и выделить разом. Если речь идет об одной ячейке, то ещё проще (как показано выше).

Вы напрасно не сформулировали всю задачу целиком. Мы бы предложили более эффективное решение (а не как сделать то, что, возможно, не нужно совсем). Подумайте над этим...
« Последнее редактирование: 11 Май 2022, 12:23 от eeigor » Записан

Ubuntu 18.04 LTS • LibreOffice 7.3.2.2 Community
siti
Участник
**
Offline Offline

Сообщений: 47


« Ответ #12: 11 Май 2022, 12:33 »

Ругается "Свойство или метод не найдены: RangeAddresses."
Код:
Sub Test_GetCellCollection2()
Dim oSheet As Object, oRanges As Object, oRange As Object, oCell As Object
Rem Dim Cells As New Collection  'CellCollection
Dim Cells As Object: Cells = New Collection

oSheet =  ThisComponent.CurrentController.ActiveSheet
oRange = oSheet.getCellRangeByName("D9:O12")
Cells = GetCellCollection(oRange.RangeAddresses())

For Each oCell In Cells
 '   MsgBox oCell.String  'oCell.AbsoluteName
    If oCell.String Like "*Авито*" Then
        ThisComponent.CurrentController.select(oCell)  'contains "abc"
        Exit For
    End If
Next
End Sub
« Последнее редактирование: 11 Май 2022, 12:57 от siti » Записан
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 1 088


« Ответ #13: 11 Май 2022, 12:57 »

а что значит "в инвертированном диапазоне"?
Это ваша тема: выделить пустые ячейки, распространить выделение на строку и инвертировать выделение, исключив строки с пустыми ячейками. Тогда выделены будут оставшиеся строки рабочего диапазона.
Записан

Ubuntu 18.04 LTS • LibreOffice 7.3.2.2 Community
siti
Участник
**
Offline Offline

Сообщений: 47


« Ответ #14: 11 Май 2022, 13:33 »

Ошибка:Необходимо задать размерность массива.
что-то не так делаю

Код:
Sub Test_GetCellCollection2()
Dim oSheet As Object, oRanges As Object, oRange As Object, oCell As Object
Rem Dim Cells As New Collection  'CellCollection
Dim Cells As Object: Cells = New Collection

oSheet =  ThisComponent.CurrentController.ActiveSheet
oRange = oSheet.getCellRangeByName("D9:O12")
Cells = GetCellCollection(oRange)

For Each oCell In Cells
 '   MsgBox oCell.String  'oCell.AbsoluteName
    If oCell.String Like "*Авито*" Then
        ThisComponent.CurrentController.select(oCell)  'contains "abc"
        Exit For
    End If
Next
End Sub
Записан
Страниц: 1 2 »   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!