Что нового

[Данные, строки] Функция для конвертации списка из ListView в текстовую таблицу

erlik

Продвинутый
Сообщения
317
Репутация
84
Аналогичная функция от guinness, к сожалению, никуда не годится (в отличие от его _GUICtrlListView_SaveHTML), поэтому решил полностью переписать свой прежний вариант (который использовал в DllViewer) и сделать его универcальным, а не только под задачи моей программы. Может, кому то пригодится, как мне пригодилась _SaveHTML от guinness.

Код:
#include <GuiListView.au3>

; #FUNCTION# =========================================================================================================
; Name...........: _SaveListAsTxt()
; Description ...: Saves the contents of the list ListView as a text table with formatting
; Syntax.........: _SaveListAsTxt($hListView [, $aArrayMax [, $sHorSepHeader [, $sColumnSep [, $sRowSep [, $sAddingStr [,$CountSpace]]]]]])
; Parameters ....: $hListView     - Handle or identifier the ListView.
;                  $aArrayMax     - [Optional] Аn array of maximum lengths of rows in each column. [Default = -1]
;                  $sHorSepHeader - [Optional] Symbol for horizontal divider title.                [Default = '=']
;                  $sColumnSep    - [Optional] Delimiter character for the header rows of columns. [Default = '|']
;                  $sRowSep       - [Optional] Delimiter character for the rows of columns         [Default = '|']
;                  $sAddingStr    - [Optional] Аppend the number of rows and the timestamp or not. [Default = 1]
;                  $CountSpace    - [Optional] Number of spaces between lines.                     [Default = 1]
; Return values .: Success - Formatted text.
;                  Failure - Empty string.
; Author ........: Erlik (aka Garry Galler)
; Modified.......:
; Remarks........: With an array of predefined values of maximum lengths of rows in each column
;                  function works almost twice as fast.
; Example........: None
;=====================================================================================================================
Func _SaveListAsTxt($hListView, $aArrayMax =-1, $sHorSepHeader = '=', $sColumnSep = '|', $sRowSep = '|', $sAddingStr = 1, $CountSpace = 1)
	;Local $hTimer = TimerInit()
	Local $iLV_ItemCount,$iLV_ColumnCount,$aLV_TextColumn, $aLV_TextRows, $sHeader='',$sFormatText,$iWidthHeader=0, $sLine='',$iLenRow
	$iLV_ItemCount   = _GUICtrlListView_GetItemCount($hListView)    ; GUICtrlSendMsg($ListView, $LVM_GETITEMCOUNT, 0, 0)
	$iLV_ColumnCount = _GUICtrlListView_GetColumnCount($hListView)  ;_SendMessage(GUICtrlSendMsg($ListView, $LVM_GETHEADER, 0, 0), 0x1200)
    If $iLV_ItemCount <= 0 Then Return ''
    ; преобразуем коды символов, если передана не строка
	If IsInt($sHorSepHeader) Then $sHorSepHeader = Chr($sHorSepHeader)
	If IsInt($sColumnSep)    Then $sColumnSep    = Chr($sColumnSep)
	If IsInt($sRowSep)       Then $sRowSep       = Chr($sRowSep)

	Local $aDataColumns[$iLV_ColumnCount][3]
	For $i = 0 To $iLV_ColumnCount-1
		$aLV_TextColumn = _GUICtrlListView_GetColumn($hListView,$i)
		$aDataColumns[$i][0] = $aLV_TextColumn[5]            ; текст заголовка колонки
		$aDataColumns[$i][1] = StringLen($aLV_TextColumn[5]) ; длина  текста заголовка колонки
		$aDataColumns[$i][2] = StringLen($aLV_TextColumn[5]) ; максимальная длина текста в строке пункта колонки, начальное значение - длина текста заголовка колонки
	Next

	; если был передан массив максимальных значений длин текста пунктов колонок, то используем эти значения
	If Ubound($aArrayMax)>= $iLV_ColumnCount Then
	    For $i=0 To $iLV_ColumnCount-1
		    If $aArrayMax[$i]> $aDataColumns[$i][1] Then $aDataColumns[$i][2]=$aArrayMax[$i]
		Next
	; иначе вычисляем максимальные значения перебором всего списка
	Else
        For $iLV_IndexItem = 0 To $iLV_ItemCount -1
	    $aLV_TextRows = _GUICtrlListView_GetItemTextArray($hListView, $iLV_IndexItem)
	        If Not IsArray($aLV_TextRows) Then ContinueLoop
			For $i = 0 To $aLV_TextRows[0]-1
                $iLenRow = StringLen($aLV_TextRows[$i+1])
			    If $iLenRow > $aDataColumns[$i][2] Then
					$aDataColumns[$i][2]= $iLenRow
                EndIf
		    Next
	    Next
    EndIf

	For $i=0 To $iLV_ColumnCount-1
	    $sHeader &= StringFormat('%-' & ($aDataColumns[$i][2]+$CountSpace) & 's', $aDataColumns[$i][0]) & $sColumnSep
	Next

	$iWidthHeader = StringLen($sHeader)
	For $i = 1 To $iWidthHeader
		$sLine &= $sHorSepHeader
	Next
	$sFormatText &= $sLine   & @CRLF
	$sFormatText &= $sHeader & @CRLF
	$sFormatText &= $sLine   & @CRLF

	For $iLV_IndexItem = 0 To $iLV_ItemCount -1
	$aLV_TextRows = _GUICtrlListView_GetItemTextArray($hListView, $iLV_IndexItem)
        If Not IsArray($aLV_TextRows) Then ContinueLoop
		For $i = 0 To $aLV_TextRows[0]-1
            $sFormatText&=StringFormat('%-' & $aDataColumns[$i][2] + $CountSpace & 's',$aLV_TextRows[$i+1]) & $sRowSep
		Next
		$sFormatText &= @CRLF
    Next
    $sFormatText &= $sLine & @CRLF

	; добавляем в конец таблицы число строк и дату\время
	If $sAddingStr Then
	    Local $sStr1 = 'Total count: ' & $iLV_ItemCount
		Local $sStr2 = 'TimeStamp: ' & @MDAY & '.' & @MON & '.' & @YEAR & ' ' & @HOUR & '.' & @MIN
		Local $iMaxWidth = $iWidthHeader-Stringlen($sStr2)
		$sFormatText &= StringFormat('%-' & $iMaxWidth & 's', $sStr1) & $sStr2 &  @CRLF & $sLine
	EndIf
	;ConsoleWrite('_SaveListAsTxt:' & TimerDiff($hTimer) & @CR)
	Return $sFormatText
EndFunc


На выходе имеем строку, которую можно сохранить в файл или вставить в буфер обмена, а затем в текстовый редактор. Визуально текст будет выглядеть так:
Код:
========================================================================================
Имя функции             |Адрес      |Относительный адрес |Путь                         |
========================================================================================
D2D1ConvertColorSpace   |0x1020DB46 |0x0020DB46          |C:\Windows\system32\d2d1.dll |
D2D1CreateDevice        |0x1020DC29 |0x0020DC29          |C:\Windows\system32\d2d1.dll |
D2D1CreateDeviceContext |0x1020DD4F |0x0020DD4F          |C:\Windows\system32\d2d1.dll |
D2D1SinCos              |0x1020DEC2 |0x0020DEC2          |C:\Windows\system32\d2d1.dll |
D2D1Tan                 |0x1020DF27 |0x0020DF27          |C:\Windows\system32\d2d1.dll |
D2D1Vec3Length          |0x1020DF6A |0x0020DF6A          |C:\Windows\system32\d2d1.dll |
D2D1CreateFactory       |0x1020E11E |0x0020E11E          |C:\Windows\system32\d2d1.dll |
D2D1MakeRotateMatrix    |0x102153A1 |0x002153A1          |C:\Windows\system32\d2d1.dll |
D2D1MakeSkewMatrix      |0x102153E6 |0x002153E6          |C:\Windows\system32\d2d1.dll |
D2D1IsMatrixInvertible  |0x10215433 |0x00215433          |C:\Windows\system32\d2d1.dll |
D2D1InvertMatrix        |0x102154AC |0x002154AC          |C:\Windows\system32\d2d1.dll |
========================================================================================
Total count: 11                                              TimeStamp: 02.03.2014 17.30
========================================================================================


Код:
;Вызывать либо так:
Local $sText = _SaveListAsTxt($ListView) 
;либо так:
Local $aTest[4]=[70,10,10,70] ; массив на четыре колонки - каждое значение максимальная длина строки текста в колонке.
Local $sText = _SaveListAsTxt($ListView,$aTest[4])


Как указано в шапке функции, вариант с передачей массива заранее определенных максимальных значений длины строк пунктов работает быстрее (в 1.5 -2 раза), так как скрипту не нужно полностью перебирать весь список (для определения указанных значений это, как вы понимаете, единственный способ).
Разница становится заметна на списках с более 1000-2000 строк. На списки в 100-200 строк дополнительный перебор оказывает минимальное по времени влияние.
 
  • Like
Реакции: Norm
Верх