RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1196503
Accepted
DiD
DiD
Asked:2021-10-28 06:36:41 +0000 UTC2021-10-28 06:36:41 +0000 UTC 2021-10-28 06:36:41 +0000 UTC

LibreOffice Calc (Excel) 的简单宏。在哪里可以找到信息?

  • 772

尽管任务简单而极简,但它打破了我的头脑。

有一个 XLS 文件,其中有一个包含 160000 多行不同数字的表格。

需要:

  1. 查找所有单元格为空的所有行;
  2. 在每条这样的线上方/下方画一条线;
  3. 删除整个空行。

事实证明,有必要从这样的文件:

在此处输入图像描述

制作这样的文档:

在此处输入图像描述

更新

问题自行解决了。感谢您的时间。没有什么比爱心人士的支持更能激发灵感了。

在编写宏时,使用了以下资源:

  • 应用程序的 Visual Basic (VBA) 语言参考

  • OpenOffice 论坛(英文)

  • 在线 LibreOffice 文档(英文)

  • LibreOffice 计算指南 6.4

  • 基本 IDE(英文)

  • 基本概述(英文)

  • BASIC 结构化数据类型

  • 基本计算

  • 基本事件

  • BASIC 运行时库

  • BASIC 运行时参数

  • 基本文件(英文)

  • 基本对话(英文)

  • Apache OpenOffice BASIC 编程指南

特别是 OpenOffice BASIC 指南的特定页面:

  • 电子表格文档的结构

  • 行和列

  • 单元格和范围

  • 格式化电子表格文档

  • 编辑电子表格文档

该解决方案标志着@JohnSUN同志的答案。

生成的宏代码:

    REM  *****  BASIC  *****

    Sub Main
       Dim oDoc As Object
       Dim oSheet As Object
       Dim oCellRange As Object
       Dim oCursor As Object   
       Dim lRowCnt As Long
       Dim lColCnt As Long
       Dim lRowCur As Long
       Dim bEmptyRow As Boolean
       Dim oBorder As Object
       Dim BLine As New com.sun.star.table.BorderLine
       
       ' устанавливаем ширину рисуемой линии
       BLine.OuterLineWidth = 60
       ' устанавливаем цвет рисуемой линии
       BLine.Color = RGB(0, 0, 0)
        
       ' текущий документ
       oDoc = ThisComponent  
 
       ' активная страница
       oSheet = oDoc.getCurrentController.activeSheet 
 
       ' определяем количество колонок по первой строке
       lColCnt = 0
       While oSheet.getCellByPosition(lColCnt, 0).type <> com.sun.star.table.CellContentType.EMPTY
          lColCnt = lColCnt + 1
       Wend
       
       ' определяем количество строк
       oCursor = oSheet.createCursor
       oCursor.gotoEndOfUsedArea(True)
       lRowCnt = Curs.Rows.Count 
   
       ' устанавливаем текущую строку
       lRowCur = 1
       ' основной цикл макроса
       while lRowCur < lRowCnt
          ' проверяем пустая ли текущая строка
          bEmptyRow = true
          For cColCur = 0 to lColCnt-1
             If oSheet.getCellByPosition(cColCur, lRowCur).Type <> com.sun.star.table.CellContentType.EMPTY Then bEmptyRow  = false
          Next cColCur
         
          If bEmptyRow Then
             ' если найдена пустая строка

             ' выделяем строку выше 
             oCellRange = oSheet.getCellRangeByPosition(0, lRowCur-1, lColCnt-1, lRowCur-1)
             ' рисуем линию по нижнему бортику ячеек
             oBorder = oCellRange.TableBorder
             oBorder.BottomLine = BLine
             oCellRange.TableBorder = oBorder
             ' удяляем одну строку
             oSheet.rows.removeByIndex(lRowCur, 1)
             ' количество строк уменьшилось на одно после удаления
             lRowCnt = lRowCnt - 1 
          Else
             ' если найдена не пустая строка

             ' инкремент индекса текущей строки
             lRowCur = lRowCur + 1        
          End If
         
       Wend
      
       ' дальнейшие строки кода выполняют не входившие в условия задачи действия, 
       ' а именно рисуют внешнюю рамку
        oCellRange = oSheet.getCellRangeByPosition(0, 0, lColCnt-1, lRowCnt-1)
        oBorder = oCellRange.TableBorder
        oBorder.BottomLine = BLine    
        oBorder.TopLine = BLine    
        oBorder.LeftLine = BLine    
        oBorder.RightLine = BLine
        oCellRange.TableBorder = oBorder
          
    End Sub
excel
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    JohnSUN
    2021-10-28T23:56:08Z2021-10-28T23:56:08Z

    其实,“亲手做”这个想法也不错。如果您知道一些使用表格的技巧,那么它确实比编写宏要快。

    例如,您可以使用此处的第四种方法

    必须在要删除的行下划线有点棘手,但这可以通过过滤器轻松解决。

    由于这个问题是关于宏的,所以代码可能是这样的:

    Option Explicit
    
    Sub RemoveEmptyRowsAndMark
    Dim oSheet As Variant
    Dim oCursor As Variant
    Dim LastUsedColumn As Long
    Dim LastUsedRow As Long
    
    Dim oDescriptor As Variant  ' Используется как дескриптор филтрацмм и как дескриптор сортировки '
    
    Dim aRows As Variant
    Dim oRange As Variant
    Rem Структура aBorder позволит отчеркнуть удалённую строку:
    Dim aBorder As Variant
    Rem Лист нужно будет отфильтровать:
    Dim aFilterFields(0) As New com.sun.star.sheet.TableFilterField
    Dim aFilterField As New com.sun.star.sheet.TableFilterField
    
    Rem  В качестве листа для чистки использовать активный лист:
        oSheet = ThisComponent.getCurrentController().getActiveSheet()
    Rem С помощью курсора ограничим область просмотра только рабочим диапазоном
        oCursor = oSheet.createCursor()
        oCursor.gotoEndOfUsedArea(True)
        LastUsedRow = oCursor.getRangeAddress().EndRow
    Rem Если лист весь пустой или есть только одна первая строка, то делать нечего:
        If LastUsedRow < 1 Then Exit Sub 
        LastUsedColumn = oCursor.getRangeAddress().EndColumn
    Rem В следующей колонке, первой за LastUsedColumn, пишем формулу, которая проверит текущую строку на наличие хоть чего-нибудь и
    Rem проставит номер строки или "пустую ячейку"
    Rem (Чтобы не вычислять букву колонки для формулы вида Rem =IF(COUNTA($A1:<последняя колонка>1);ROW();"")
    Rem используем нотацию R1C1. Ввод такой формулы немного сложнее, чем просто .setFormula()
        setRCFormula("=IF(COUNTA(RC1:RC[-1]);ROW();"""")", oSheet.getCellByPosition(LastUsedColumn+1,0))
    Rem И ещё одна формула - "необходимо отчеркнуть текущую строку"
        setRCFormula("=AND(RC[-1]<>"""";R[1]C[-1]="""")", oSheet.getCellByPosition(LastUsedColumn+2,0))
    Rem Заполним этими формулами колонки до LastUsedRow (на 160К+ строк придётся немного подождать)
        oSheet.getCellRangeByPosition(LastUsedColumn+1, 0, LastUsedColumn+2, LastUsedRow).fillAuto(com.sun.star.sheet.FillDirection.TO_BOTTOM, 1)
    
    Rem Теперь отфильтруем весь диапазон с этими двумя дополнительными колонками
    Rem по значению ИСТИНА в последней колонке. Повторяем выделение UsedRange (он теперь шире на две колонки):
        oCursor = oSheet.createCursor()
        oCursor.gotoEndOfUsedArea(True)
    Rem Фильтрация:
        oDescriptor = oCursor.createFilterDescriptor(True)
        aFilterField.Field = LastUsedColumn + 2 ' Колонка с признаком "необходимо отчеркнуть текущую строку"
        aFilterField.IsNumeric = true
        aFilterField.Operator = com.sun.star.sheet.FilterOperator.EQUAL
        aFilterField.NumericValue = 1
        aFilterFields(0) = aFilterField
        oDescriptor.setFilterFields(aFilterFields)
        oCursor.filter(oDescriptor)
    Rem Теперь видны только строки, которые нужно отчеркнуть линией
        oRange = oCursor.queryVisibleCells()
        aBorder = oRange.BottomBorder       ' Копируем существующую структуру границ диапазона в переменную '
    Rem и изменяем её по своему усмотрению
        aBorder.OuterLineWidth = 50 ' Толщину линии для отчёркивания можно сделать и больше '
        aBorder.Color = 255 ' Цвет можно задать любой '
        oRange.BottomBorder = aBorder       ' Возвращаем измененную структуру на место - теперь все видимые строки получили нижнюю границу '
    Rem Удалим фильтр и отобразим скрытые строки
        aRows = oCursor.getRows()
        aRows.IsFiltered = False
        aRows.IsVisible = True
    Rem Теперь осталось отсортировать диапазон по предпоследней колонке:
        Call sortRange(ThisComponent, oCursor, LastUsedColumn + 1, False)
    Rem ... и удалить вспомогательные колонки:
        oSheet.getColumns().removeByIndex (LastUsedColumn+1, 2)
    Rem Вот и всё
    End Sub
    
    Sub setRCFormula(sRCFormula As String, oCell As Variant)
    Rem (см. https://ask.libreoffice.org/en/question/149099/how-to-use-r1c1-formulae-in-calc-macros/)
    Dim hParser As Variant
        hParser = ThisComponent.CreateInstance( "com.sun.star.sheet.FormulaParser" )
        hParser.FormulaConvention = com.sun.star.sheet.AddressConvention.XL_R1C1
        oCell.SetTokens(hParser.ParseFormula(sRCFormula, oCell.CellAddress))
    End Sub
    
    Sub sortRange(oDoc As Variant, oRange As Variant, Optional nColumn As Long, Optional bContainsHeader As Boolean)
    Dim aSortFields(0) As New com.sun.star.util.SortField
    Dim aSortDesc(1) As New com.sun.star.beans.PropertyValue
        If IsMissing(nColumn) Then nColumn = 0
        If IsMissing(bContainsHeader) Then bContainsHeader = True
        
        oDoc.getCurrentController().select(oRange)
        aSortFields(0).Field = nColumn
        aSortFields(0).SortAscending = TRUE
        aSortDesc(0).Name = "SortFields"
        aSortDesc(0).Value = aSortFields()
        aSortDesc(1).Name = "ContainsHeader"
        aSortDesc(1).Value = bContainsHeader
        oRange.Sort(aSortDesc())
    Rem уберём выделение
        oDoc.getCurrentController().Select(oDoc.createInstance("com.sun.star.sheet.SheetCellRanges"))
    End Sub
    
    • 1

相关问题

  • 使用 VBA 在 Excel 中插入图片

  • 选择哪里(EXCEL)

  • 两列的条件格式

  • 如何按文章比较两个表格?

  • 打开工作簿时,跳转到当前日期的单元格[关闭]

  • 在工作簿之间复制数据。WBA代码加速

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5