Что нового

Таблица в массив, возможно ли?

rivega

Новичок
Сообщения
45
Репутация
1
Есть таблица вида: наименование, значение(2 столбца, n строк).


Возможно ли считать данную таблицу за один проход и вернуть массив вида(наименование,значение), если да , то как?
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
rivega
Таблица-то где, в каком виде? Интернет-страница, лист excel?
 
Автор
R

rivega

Новичок
Сообщения
45
Репутация
1
http://autoit-script.ru/index.php?topic=12724.msg81942#msg81942


Таблица в окне программы EsiTronic, поячеечно с ней можно работать командами:
Код:
$chn = ControlGetHandle($hWnd, "", "[CLASS:SysListView32; INSTANCE:2]")
$r = ControlListView($hWnd, "", $chn, "GetItemCount")
$aItem = _GUICtrlListView_GetItemTextArray($chn,1)

я правильно ответил на не заданный Вами вопрос?
 
Автор
R

rivega

Новичок
Сообщения
45
Репутация
1
http://autoit-script.ru/index.php?topic=12724.msg81954#msg81954

_GUICtrlListView_AddArray - Добавляет пункты из массива в ListView

а мне наоборот нужно: из ListView в массив.
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
rivega
Из справки к _GUICtrlListView_GetItemTextArray
Код:
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <Array.au3>

$Debug_LV = False ; Check ClassName being passed to ListView functions, set to True and use a handle to another control to see it work

GUICreate('ListView Get Item Text Array', 400, 300)

$hListView = GUICtrlCreateListView('col1|col2', 2, 2, 394, 268)
GUICtrlCreateListViewItem('line1|data1', $hListView)
GUICtrlCreateListViewItem('line2|data2', $hListView)
GUICtrlCreateListViewItem('line3|data3', $hListView)
GUICtrlCreateListViewItem('line4|data4', $hListView)
GUICtrlCreateListViewItem('line5|data5', $hListView)

GUISetState()


$r = _GUICtrlListView_GetItemCount($hListView)

Dim $avArray[$r][2]

For $i = 0 To $r - 1
	$aItem = _GUICtrlListView_GetItemTextArray($hListView, $i)
	$avArray[$i][0] = $aItem[1]
	$avArray[$i][1] = $aItem[2]	
Next

_ArrayDisplay($avArray)


Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()

Соответственно, вместо $hListView нужно подставить хэндл элемента SysListView32 из нужной программы
 
Автор
R

rivega

Новичок
Сообщения
45
Репутация
1
AZJIO
_GUICtrlListView_AddArray - Добавляет пункты из массива в ListView
а мне наоборот нужно: из ListView в массив.
Пишу Вам.(если я не прав и понимаю текст справки прямолинейно, то пожалуйста исправьте меня)
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
rivega
А вы в курсе что то что я предлагаю отличается от того что вы пишите?
 
Автор
R

rivega

Новичок
Сообщения
45
Репутация
1
AZJIO
Да, вы правы, я не внимателен.



Добавлено:
Сообщение автоматически объединено:

AZJIO

Если вы имеете в виду вот этот вариант, то но мне не подходит(я примерно так изначально и делал, очень долго получается с моей таблицей.....примерно 1с-1.5с)
Код:
Func _GUICtrlListView_CreateArray($hListView, $sDelimeter = '|')
    Local $iColumnCount = _GUICtrlListView_GetColumnCount($hListView), $iDim = 0, $iItemCount = _GUICtrlListView_GetItemCount($hListView)
    If $iColumnCount < 3 Then
        $iDim = 3 - $iColumnCount
    EndIf
    If $sDelimeter = Default Then
        $sDelimeter = '|'
    EndIf

    Local $aColumns = 0, $aReturn[$iItemCount + 1][$iColumnCount + $iDim] = [[$iItemCount, $iColumnCount, '']]
    For $i = 0 To $iColumnCount - 1
        $aColumns = _GUICtrlListView_GetColumn($hListView, $i)
        $aReturn[0][2] &= $aColumns[5] & $sDelimeter
    Next
    $aReturn[0][2] = StringTrimRight($aReturn[0][2], StringLen($sDelimeter))

    For $i = 0 To $iItemCount - 1
        For $j = 0 To $iColumnCount - 1
            $aReturn[$i + 1][$j] = _GUICtrlListView_GetItemText($hListView, $i, $j)
        Next
    Next
    Return SetError(Number($aReturn[0][0] = 0), 0, $aReturn)
EndFunc   ;==>_GUICtrlListView_CreateArray



то что предложил WSWR в моем случае работает 0.5с....



мне это критично, потому что таблиц для считывания очень много.
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
rivega
Почему мой тест показывает скорость функции _GUICtrlListView_CreateArray в полтора раза быстрее?
Код:
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <Array.au3>
#include <_GUICtrlListView_CreateArray.au3>

GUICreate('Тест', 400, 300)

$hListView = GUICtrlCreateListView('col1|col2', 2, 2, 394, 268)
For $i = 1 To 5000
	GUICtrlCreateListViewItem('line1|data1', $hListView)
Next
GUISetState()

$timer1 = TimerInit()
$avArray = _GUICtrlListView_CreateArray($hListView)
$timer1 = 'Время1 : ' & Round(TimerDiff($timer1), 2) & ' мсек'

$timer2 = TimerInit()
$r = _GUICtrlListView_GetItemCount($hListView)
Dim $avArray[$r][2]
For $i = 0 To $r - 1
    $aItem = _GUICtrlListView_GetItemTextArray($hListView, $i)
    $avArray[$i][0] = $aItem[1]
    $avArray[$i][1] = $aItem[2] 
Next
$timer2 = 'Время2 : ' & Round(TimerDiff($timer2), 2) & ' мсек'

MsgBox(0, 'Сообщение', $timer1 &@CRLF& $timer2)

Do
Until GUIGetMsg() = -3


Теоритически вот самое быстрое:
Код:
$c = ControlListView($hGui, "", "SysListView321", "GetItemCount")
Local $asArray[$c][2]
For $i = 0 To $c - 1
    $asArray[$i][0] = ControlListView($hGui, "", "SysListView321", "GetText", $i, 0)
    $asArray[$i][1] = ControlListView($hGui, "", "SysListView321", "GetText", $i, 1)
Next
 
Автор
R

rivega

Новичок
Сообщения
45
Репутация
1
AZJIO
Сравнил, вы опять оказались правы. я напутал с секундами и миллисекундами.
сейчас получилось 63.6, 0.05 и 4.8 секунд соответственно.

Код:
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <Array.au3>
#include <_GUICtrlListView_CreateArray.au3>

$Debug_LV = False ; Check ClassName being passed to ListView functions, set to True and use a handle to another control to see it work  
WinActivate('ESI[tronic] - Выбор автомобиля по наименованию')
$hWnd= WinWait('ESI[tronic] - Выбор автомобиля по наименованию')
$iTimer = TimerInit()

$chn = ControlGetHandle($hWnd, "", "[CLASS:SysListView32; INSTANCE:2]")
$r = _GUICtrlListView_GetItemCount($chn)
Dim $avArray[$r][2]
For $i = 0 To $r - 1
    $aItem = _GUICtrlListView_GetItemTextArray($chn, $i)
    $avArray[$i][0] = $aItem[1]
    $avArray[$i][1] = $aItem[2] 
Next
$timer1= Round(TimerDiff($iTimer), 2)
$timer2 = TimerInit()
$c = ControlListView($chn, "", "SysListView321", "GetItemCount")
Local $asArray[$c][2]
For $i = 0 To $c - 1
    $asArray[$i][0] = ControlListView($chn, "", "SysListView321", "GetText", $i, 0)
    $asArray[$i][1] = ControlListView($chn, "", "SysListView321", "GetText", $i, 1)
 Next
;MsgBox('','','Время2 : ' & Round(TimerDiff($timer2), 2) & ' мсек')
 $timer2= Round(TimerDiff($timer2), 2)
 ;_ArrayDisplay($avArray)
 

$timer3 = TimerInit()
$avArray = _GUICtrlListView_CreateArray($chn)
$timer3 = 'Время1 : ' & Round(TimerDiff($timer3), 2) & ' мсек'


MsgBox(0, 'Сообщение', $timer1 &@CRLF& $timer2 &@CRLF& $timer3)

Do
Until GUIGetMsg() = -3
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
rivega,
Так еще быстрее должно работать.
Код:
#include <GuiListView.au3>

$hListView = ControlGetHandle('[Title:Select an Exit Node; Class:#32770]', '', '[CLASS:SysListView32; INSTANCE:1]');AdvOR
If Not $hListView Then Exit -13
$sStart = TimerInit()
$aReturn = _GUICtrlListView_GetAllTextArray($hListView, 1, -1, '1|3')
If @error Then Exit -33
$sTime = StringFormat('%.2f msec', TimerDiff($sStart))
_ArrayDisplay($aReturn, $sTime)


#cs
	$s_RowString = '0|2|5'
	$h_ListView - only Handle
#ce
Func _GUICtrlListView_GetAllTextArray($h_ListView, $i_ItemStart = 0, $i_ItemEnd = -1, $s_RowString = -1, $s_Separator = '|')
	Local $f_Unicode, $i_CountItem, $i_CountRow, $a_Row, $t_Buffer, $p_Buffer, $t_Item, $p_Item, $a_Return[1], $i_Item, $t_MemMap, _
			$p_Memory, $p_Text, $f_InProcess, $i_Msg

	If Not IsHWnd($h_ListView) Then Return SetError(-1, 0, 0)

	$i_CountRow = _GUICtrlListView_GetColumnCount($h_ListView)
	$i_CountItem = _GUICtrlListView_GetItemCount($h_ListView)

	If $i_ItemEnd = -1 Or $i_ItemEnd = Default Then
		$i_ItemEnd = $i_CountItem - 1
	Else
		$i_ItemEnd = Abs(Int($i_ItemEnd))
		If $i_ItemEnd > $i_CountItem - 1 Then $i_ItemEnd = $i_CountItem - 1
	EndIf
	$i_ItemStart = Abs(Int($i_ItemStart))
	If $i_ItemStart > $i_CountItem - 1 Then $i_ItemStart = 0
	If $i_ItemEnd <= $i_ItemStart Then $i_ItemEnd = $i_ItemStart + 1

	If $s_RowString = -1 Or $s_RowString = Default Then
		$s_RowString = ''
		For $i = 0 To $i_CountRow - 1
			$s_RowString &= $i & $s_Separator
		Next
	EndIf
	$s_RowString = StringRegExpReplace($s_RowString, '^[^\d]+|[^\d]+$', '')
	$s_RowString = StringRegExpReplace($s_RowString, '[^\d]', $s_Separator)
	$s_RowString = StringRegExpReplace($s_RowString, '\Q' & $s_Separator & '\E{2,}', $s_Separator)

	$a_Row = StringSplit($s_RowString, $s_Separator)
	For $i = 1 To $a_Row[0]
		$a_Row[$i] = Int($a_Row[$i])
		If $a_Row[$i] > $i_CountRow - 1 Then Return SetError(-1, 0, 0)
	Next
	$a_Row = _ArrayUnique($a_Row, 1, 1)
	_ArraySort($a_Row, 0, 1)

	$f_Unicode = _GUICtrlListView_GetUnicodeFormat($h_ListView)
	If $f_Unicode Then
		$t_Buffer = DllStructCreate('wchar Text[4096]')
	Else
		$t_Buffer = DllStructCreate('char Text[4096]')
	EndIf
	$p_Buffer = DllStructGetPtr($t_Buffer)
	$t_Item = DllStructCreate($tagLVITEM)
	$p_Item = DllStructGetPtr($t_Item)
	DllStructSetData($t_Item, 'TextMax', 4096)
	If _WinAPI_InProcess($h_ListView, $_lv_ghLastWnd) Then
		DllStructSetData($t_Item, 'Text', $p_Buffer)
		$f_InProcess = True
		$i_Msg = $LVM_GETITEMTEXTW
	Else
		$i_Item = DllStructGetSize($t_Item)
		$p_Memory = _MemInit($h_ListView, $i_Item + 4096, $t_MemMap)
		$p_Text = $p_Memory + $i_Item
		DllStructSetData($t_Item, 'Text', $p_Text)
		If $f_Unicode Then
			$i_Msg = $LVM_GETITEMTEXTW
		Else
			$i_Msg = $LVM_GETITEMTEXTA
		EndIf
	EndIf
	ReDim $a_Return[$i_CountItem + 1][$a_Row[0]]
	If $f_InProcess Then
		For $i = $i_ItemStart To $i_ItemEnd
			$a_Return[0][0] += 1
			For $j = 1 To $a_Row[0]
				DllStructSetData($t_Item, 'SubItem', $a_Row[$j])
				_SendMessage($h_ListView, $i_Msg, $i, $p_Item, 0, 'wparam', 'ptr')
				$a_Return[$a_Return[0][0]][$j - 1] = DllStructGetData($t_Buffer, 'Text')
			Next
		Next
	Else
		For $i = $i_ItemStart To $i_ItemEnd
			$a_Return[0][0] += 1
			For $j = 1 To $a_Row[0]
				DllStructSetData($t_Item, 'SubItem', $a_Row[$j])
				_MemWrite($t_MemMap, $p_Item, $p_Memory, $i_Item)
				_SendMessage($h_ListView, $i_Msg, $i, $p_Memory, 0, 'wparam', 'ptr')
				_MemRead($t_MemMap, $p_Text, $p_Buffer, 4096)
				$a_Return[$a_Return[0][0]][$j - 1] = DllStructGetData($t_Buffer, 'Text')
			Next
		Next
		_MemFree($t_MemMap)
	EndIf
	ReDim $a_Return[$a_Return[0][0] + 1][$a_Row[0]]
	Return $a_Return
EndFunc   ;==>_GUICtrlListView_GetAllTextArray
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
rivega [?]
сейчас получилось 63.6, 0.05 и 4.8 секунд соответственно.
думаю 0.05 это ошибочный результат, потому что в ControlListView первый параметр - дескриптор окна, а не ListView, отсюда и быстрый вывод ошибочных результатов.


madmasles
Почему то эта функция на 1 элемент меньше возращает чем реально, вернее вставляет количество строк взамен первого элемента. А так да, быстрее.

Код:
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <Array.au3>
#include <_GUICtrlListView_CreateArray.au3>

$hGui = GUICreate('Тест', 400, 300)

$iListView = GUICtrlCreateListView('col1|col2', 2, 2, 394, 268)
$hListView = GUICtrlGetHandle(-1)
; $hListView = $iListView
For $i = 1 To 1000
	GUICtrlCreateListViewItem($i & '|data1', $iListView)
Next
GUISetState()

$timer1 = TimerInit()
$aReturn = _GUICtrlListView_GetAllTextArray($hListView, 1, -1, '0|1')
If @error Then Exit -33
$timer1 = 'Время1 : ' & Round(TimerDiff($timer1), 2) & ' мсек'

$timer2 = TimerInit()
$c = ControlListView($hGui, "", "SysListView321", "GetItemCount")
Local $asArray[$c][2]
For $i = 0 To $c - 1
	$asArray[$i][0] = ControlListView($hGui, "", "SysListView321", "GetText", $i, 0)
	$asArray[$i][1] = ControlListView($hGui, "", "SysListView321", "GetText", $i, 1)
Next
$timer2 = 'Время2 : ' & Round(TimerDiff($timer2), 2) & ' мсек'

MsgBox(0, 'Сообщение', $timer1 & @CRLF & $timer2)
_ArrayDisplay($aReturn)
_ArrayDisplay($asArray)

Do
Until GUIGetMsg() = -3

#cs
	$s_RowString = '0|2|5'
	$h_ListView - only Handle
#ce
Func _GUICtrlListView_GetAllTextArray($h_ListView, $i_ItemStart = 0, $i_ItemEnd = -1, $s_RowString = -1, $s_Separator = '|')
	Local $f_Unicode, $i_CountItem, $i_CountRow, $a_Row, $t_Buffer, $p_Buffer, $t_Item, $p_Item, $a_Return[1], $i_Item, $t_MemMap, _
			$p_Memory, $p_Text, $f_InProcess, $i_Msg

	If Not IsHWnd($h_ListView) Then Return SetError(-1, 0, 0)

	$i_CountRow = _GUICtrlListView_GetColumnCount($h_ListView)
	$i_CountItem = _GUICtrlListView_GetItemCount($h_ListView)

	If $i_ItemEnd = -1 Or $i_ItemEnd = Default Then
		$i_ItemEnd = $i_CountItem - 1
	Else
		$i_ItemEnd = Abs(Int($i_ItemEnd))
		If $i_ItemEnd > $i_CountItem - 1 Then $i_ItemEnd = $i_CountItem - 1
	EndIf
	$i_ItemStart = Abs(Int($i_ItemStart))
	If $i_ItemStart > $i_CountItem - 1 Then $i_ItemStart = 0
	If $i_ItemEnd <= $i_ItemStart Then $i_ItemEnd = $i_ItemStart + 1

	If $s_RowString = -1 Or $s_RowString = Default Then
		$s_RowString = ''
		For $i = 0 To $i_CountRow - 1
			$s_RowString &= $i & $s_Separator
		Next
	EndIf
	$s_RowString = StringRegExpReplace($s_RowString, '^[^\d]+|[^\d]+$', '')
	$s_RowString = StringRegExpReplace($s_RowString, '[^\d]', $s_Separator)
	$s_RowString = StringRegExpReplace($s_RowString, '\Q' & $s_Separator & '\E{2,}', $s_Separator)

	$a_Row = StringSplit($s_RowString, $s_Separator)
	For $i = 1 To $a_Row[0]
		$a_Row[$i] = Int($a_Row[$i])
		If $a_Row[$i] > $i_CountRow - 1 Then Return SetError(-1, 0, 0)
	Next
	$a_Row = _ArrayUnique($a_Row, 1, 1)
	_ArraySort($a_Row, 0, 1)

	$f_Unicode = _GUICtrlListView_GetUnicodeFormat($h_ListView)
	If $f_Unicode Then
		$t_Buffer = DllStructCreate('wchar Text[4096]')
	Else
		$t_Buffer = DllStructCreate('char Text[4096]')
	EndIf
	$p_Buffer = DllStructGetPtr($t_Buffer)
	$t_Item = DllStructCreate($tagLVITEM)
	$p_Item = DllStructGetPtr($t_Item)
	DllStructSetData($t_Item, 'TextMax', 4096)
	If _WinAPI_InProcess($h_ListView, $_lv_ghLastWnd) Then
		DllStructSetData($t_Item, 'Text', $p_Buffer)
		$f_InProcess = True
		$i_Msg = $LVM_GETITEMTEXTW
	Else
		$i_Item = DllStructGetSize($t_Item)
		$p_Memory = _MemInit($h_ListView, $i_Item + 4096, $t_MemMap)
		$p_Text = $p_Memory + $i_Item
		DllStructSetData($t_Item, 'Text', $p_Text)
		If $f_Unicode Then
			$i_Msg = $LVM_GETITEMTEXTW
		Else
			$i_Msg = $LVM_GETITEMTEXTA
		EndIf
	EndIf
	ReDim $a_Return[$i_CountItem + 1][$a_Row[0]]
	If $f_InProcess Then
		For $i = $i_ItemStart To $i_ItemEnd
			$a_Return[0][0] += 1
			For $j = 1 To $a_Row[0]
				DllStructSetData($t_Item, 'SubItem', $a_Row[$j])
				_SendMessage($h_ListView, $i_Msg, $i, $p_Item, 0, 'wparam', 'ptr')
				$a_Return[$a_Return[0][0]][$j - 1] = DllStructGetData($t_Buffer, 'Text')
			Next
		Next
	Else
		For $i = $i_ItemStart To $i_ItemEnd
			$a_Return[0][0] += 1
			For $j = 1 To $a_Row[0]
				DllStructSetData($t_Item, 'SubItem', $a_Row[$j])
				_MemWrite($t_MemMap, $p_Item, $p_Memory, $i_Item)
				_SendMessage($h_ListView, $i_Msg, $i, $p_Memory, 0, 'wparam', 'ptr')
				_MemRead($t_MemMap, $p_Text, $p_Buffer, 4096)
				$a_Return[$a_Return[0][0]][$j - 1] = DllStructGetData($t_Buffer, 'Text')
			Next
		Next
		_MemFree($t_MemMap)
	EndIf
	ReDim $a_Return[$a_Return[0][0] + 1][$a_Row[0]]
	Return $a_Return
EndFunc   ;==>_GUICtrlListView_GetAllTextArray
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
AZJIO [?]
Почему то эта функция на 1 элемент меньше возращает чем реально, вернее вставляет количество строк взамен первого элемента.
У вас $i_ItemStart = 1 и функция берет текст с 1-ого индекса, а не с 0-ого.
Я делал эту функцию для обработки чужого окна. Если для своего, то лучше(быстрее) получать текст с помощью GUICtrlSendMsg. На форуме где-то есть пример кода.

Так у меня быстрее всего работает.
Код:
#include <Array.au3>

$hWin = WinGetHandle('[Title:Select an Exit Node; Class:#32770]')
$hListView = ControlGetHandle($hWin, '', '[CLASS:SysListView32; INSTANCE:1]')
$sStart = TimerInit()

$iItems = ControlListView($hWin, '', $hListView, 'GetItemCount')
$iSubitems = ControlListView($hWin, '', $hListView, 'GetSubItemCount')
Local $aReturn[$iItems + 1][$iSubitems] = [[$iItems, $iSubitems]]
For $i = 1 To $iItems
	For $j = 0 To $iSubitems - 1
		$aReturn[$i][$j] = ControlListView($hWin, '', $hListView, 'GetText', $i - 1, $j)
	Next
Next
$sTime = StringFormat('%.2f msec', TimerDiff($sStart))
_ArrayDisplay($aReturn, $sTime)
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
Итог:
_GUICtrlListView_GetAllTextArray = 160 мсек
ControlListView в цикле = 180-200 мсек
Другие варианты рассматривать не стал, как намного медленее.
_GUICtrlListView_CreateArray = 250 мсек (с идентификатором)
_GUICtrlListView_CreateArray = 450 мсек (с дескриптором)

Код:
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <Array.au3>
#include <_GUICtrlListView_CreateArray.au3>

$hGui = GUICreate('Тест', 400, 300)

$iListView = GUICtrlCreateListView('col1|col2', 2, 2, 394, 268)
$hListView = GUICtrlGetHandle(-1)
; $hListView = $iListView
For $i = 1 To 1000
	GUICtrlCreateListViewItem($i & '|data1', $iListView)
Next
GUISetState()

$timer1 = TimerInit()
$aReturn = _GUICtrlListView_GetAllTextArray($hListView, 0, -1, '0|1')
If @error Then Exit -33
$timer1 = 'Время1 : ' & Round(TimerDiff($timer1), 2) & ' мсек'

$timer2 = TimerInit()
$c = ControlListView($hGui, "", $hListView, "GetItemCount")
Local $asArray[$c][2]
For $i = 0 To $c - 1
	$asArray[$i][0] = ControlListView($hGui, '', $hListView, 'GetText', $i, 0)
	$asArray[$i][1] = ControlListView($hGui, '', $hListView, 'GetText', $i, 1)
Next
$timer2 = 'Время2 : ' & Round(TimerDiff($timer2), 2) & ' мсек'

MsgBox(0, 'Сообщение', $timer1 & @CRLF & $timer2)
; _ArrayDisplay($aReturn)
; _ArrayDisplay($asArray)

Do
Until GUIGetMsg() = -3



#cs
	$s_RowString = '0|2|5'
	$h_ListView - only Handle
#ce
Func _GUICtrlListView_GetAllTextArray($h_ListView, $i_ItemStart = 0, $i_ItemEnd = -1, $s_RowString = -1, $s_Separator = '|')
	Local $f_Unicode, $i_CountItem, $i_CountRow, $a_Row, $t_Buffer, $p_Buffer, $t_Item, $p_Item, $a_Return[1], $i_Item, $t_MemMap, _
			$p_Memory, $p_Text, $f_InProcess, $i_Msg

	If Not IsHWnd($h_ListView) Then Return SetError(-1, 0, 0)

	$i_CountRow = _GUICtrlListView_GetColumnCount($h_ListView)
	$i_CountItem = _GUICtrlListView_GetItemCount($h_ListView)

	If $i_ItemEnd = -1 Or $i_ItemEnd = Default Then
		$i_ItemEnd = $i_CountItem - 1
	Else
		$i_ItemEnd = Abs(Int($i_ItemEnd))
		If $i_ItemEnd > $i_CountItem - 1 Then $i_ItemEnd = $i_CountItem - 1
	EndIf
	$i_ItemStart = Abs(Int($i_ItemStart))
	If $i_ItemStart > $i_CountItem - 1 Then $i_ItemStart = 0
	If $i_ItemEnd <= $i_ItemStart Then $i_ItemEnd = $i_ItemStart + 1

	If $s_RowString = -1 Or $s_RowString = Default Then
		$s_RowString = ''
		For $i = 0 To $i_CountRow - 1
			$s_RowString &= $i & $s_Separator
		Next
	EndIf
	$s_RowString = StringRegExpReplace($s_RowString, '^[^\d]+|[^\d]+$', '')
	$s_RowString = StringRegExpReplace($s_RowString, '[^\d]', $s_Separator)
	$s_RowString = StringRegExpReplace($s_RowString, '\Q' & $s_Separator & '\E{2,}', $s_Separator)

	$a_Row = StringSplit($s_RowString, $s_Separator)
	For $i = 1 To $a_Row[0]
		$a_Row[$i] = Int($a_Row[$i])
		If $a_Row[$i] > $i_CountRow - 1 Then Return SetError(-1, 0, 0)
	Next
	$a_Row = _ArrayUnique($a_Row, 1, 1)
	_ArraySort($a_Row, 0, 1)

	$f_Unicode = _GUICtrlListView_GetUnicodeFormat($h_ListView)
	If $f_Unicode Then
		$t_Buffer = DllStructCreate('wchar Text[4096]')
	Else
		$t_Buffer = DllStructCreate('char Text[4096]')
	EndIf
	$p_Buffer = DllStructGetPtr($t_Buffer)
	$t_Item = DllStructCreate($tagLVITEM)
	$p_Item = DllStructGetPtr($t_Item)
	DllStructSetData($t_Item, 'TextMax', 4096)
	If _WinAPI_InProcess($h_ListView, $_lv_ghLastWnd) Then
		DllStructSetData($t_Item, 'Text', $p_Buffer)
		$f_InProcess = True
		$i_Msg = $LVM_GETITEMTEXTW
	Else
		$i_Item = DllStructGetSize($t_Item)
		$p_Memory = _MemInit($h_ListView, $i_Item + 4096, $t_MemMap)
		$p_Text = $p_Memory + $i_Item
		DllStructSetData($t_Item, 'Text', $p_Text)
		If $f_Unicode Then
			$i_Msg = $LVM_GETITEMTEXTW
		Else
			$i_Msg = $LVM_GETITEMTEXTA
		EndIf
	EndIf
	ReDim $a_Return[$i_CountItem + 1][$a_Row[0]]
	If $f_InProcess Then
		For $i = $i_ItemStart To $i_ItemEnd
			$a_Return[0][0] += 1
			For $j = 1 To $a_Row[0]
				DllStructSetData($t_Item, 'SubItem', $a_Row[$j])
				_SendMessage($h_ListView, $i_Msg, $i, $p_Item, 0, 'wparam', 'ptr')
				$a_Return[$a_Return[0][0]][$j - 1] = DllStructGetData($t_Buffer, 'Text')
			Next
		Next
	Else
		For $i = $i_ItemStart To $i_ItemEnd
			$a_Return[0][0] += 1
			For $j = 1 To $a_Row[0]
				DllStructSetData($t_Item, 'SubItem', $a_Row[$j])
				_MemWrite($t_MemMap, $p_Item, $p_Memory, $i_Item)
				_SendMessage($h_ListView, $i_Msg, $i, $p_Memory, 0, 'wparam', 'ptr')
				_MemRead($t_MemMap, $p_Text, $p_Buffer, 4096)
				$a_Return[$a_Return[0][0]][$j - 1] = DllStructGetData($t_Buffer, 'Text')
			Next
		Next
		_MemFree($t_MemMap)
	EndIf
	ReDim $a_Return[$a_Return[0][0] + 1][$a_Row[0]]
	Return $a_Return
EndFunc   ;==>_GUICtrlListView_GetAllTextArray
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
madmasles
Вот, с первого раза
Время1 : 158.77 мсек
Время2 : 177.75 мсек
WinXP, AutoIt 3.3.6.1
Не пойму как такое может быть, запускал много раз результаты случайные но вокруг средне статистического.
Теперь наверно следует написать функцию на основе ControlListView с проверками всех ошибок.


Код:
; AZJIO
; http://autoit-script.ru/index.php/topic,12724.msg82043.html#msg82043
#include <WinAPI.au3>
#include <Array.au3>

$hGui = GUICreate('Тест', 400, 300)
$iListView = GUICtrlCreateListView('Строка     |Данные', 2, 2, 394, 268)
; $iListView = GUICtrlCreateListView('Строка', 2, 2, 394, 268)
$hListView = GUICtrlGetHandle(-1)
; $hListView = $iListView
For $i = 1 To 1000
	GUICtrlCreateListViewItem('Строка ' & $i & '|' & Random(1000, 9999, 1), $iListView)
	; GUICtrlCreateListViewItem('Строка '&$i, $iListView)
Next
GUISetState()

$sStart = TimerInit()
$aReturn = _GUICtrlListView_GetAllTextToArray($hListView)
$extended = @extended
If @error < 0 Then Exit MsgBox(0, 'Сообщение', 'Список пустой')
$sTime = StringFormat('%.2f msec', TimerDiff($sStart))
MsgBox(262144, 'Информация', _
		"Пунктов: " & _WinAPI_LoWord($extended) & @LF & _
		"Колонок: " & _WinAPI_HiWord($extended))
_ArrayDisplay($aReturn, $sTime)

Func _GUICtrlListView_GetAllTextToArray($hListView)
	If Not IsHWnd($hListView) Then ; Если не дескриптор
		$hListView = GUICtrlGetHandle($hListView)
		If Not IsHWnd($hListView) Then Return SetError(1, 0, 0)
	EndIf
	Local $hWin, $iItems, $iSubitems
	$hWin = _WinAPI_GetParent($hListView) ; Получает дескриптор родительского окна
	If Not $hWin Then Return SetError(2, 0, 0)
	$iItems = ControlListView($hWin, '', $hListView, 'GetItemCount') ; получает количество пунктов
	If Not $iItems Then Return SetError(-1, 0, 0)
	$iSubitems = ControlListView($hWin, '', $hListView, 'GetSubItemCount') ; получает количество колонок
	; If Not $iSubitems Then Return SetError(-2, 0, 0)
	If Not $iSubitems Then $iSubitems = 1 ; Если получены пункты, то колонок не может быть 0
	Local $aReturn[$iItems][$iSubitems] = [[$iItems]]
	; For $i = 0 To $iItems - 1 ; Для оптимизиции цикл с $iSubitems лучше сделать снаружи
		; For $j = 0 To $iSubitems - 1
			; $aReturn[$i][$j] = ControlListView($hWin, '', $hListView, 'GetText', $i, $j)
		; Next
	; Next
	For $j = 0 To $iSubitems - 1 ; Оптимизированней, потому что строк обычно больше чем колонок
		For $i = 0 To $iItems - 1
			$aReturn[$i][$j] = ControlListView($hWin, '', $hListView, 'GetText', $i, $j)
		Next
	Next
	Return SetError(0, _WinAPI_MakeLong($iItems, $iSubitems), $aReturn)
EndFunc   ;==>_GUICtrlListView_GetAllTextToArray
 
  • Like
Реакции: Norm

xaker

Знающий
Сообщения
52
Репутация
16
AZJIO
на win7 x32 этот вариант от 38 до 48 мсек
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
xaker
С чем сравнивать? Процессоры то у всех разные. Предыдущий вариант содержит две версии для теста.
 
Верх