Что нового

[Автоматизация] Потоковое получение данных из Excel и работа с буфером обмена.

valdur2000

Знающий
Сообщения
155
Репутация
7
Здравствуйте, уважаемые форумчане. Вопрос вот о чем:
Есть Excel'евская таблица с подготовленными заранее данными (10 столбцов, а строк каждый раз по-разному, от 50 до 1000) и есть маска в IE (Class: SunAwtCanvas в которой реально ничего не ловится) с текстовыми полями, куда данные соответственно вставляются по Mouseclick и ClipGet. Я открываю таблицу, копирую весь массив в Clipmate (прога для работы с Clipboard), там устанавливаю поячеечную вставку данных и дальше все делает AutoIt. Так вот при быстрой работе, Clipmate не успевает перепрыгивать с ячейки на ячейку и данные либо не вставляются в очередную ячейку, а значит при подтверждении данных выйдет ошибка, либо вставляются, но Clipmate не успевает перескочить и одинаковые данные вставляются в две или более ячеек, а значит опять ошибка.
В предыдущей теме проблема пустой ячейки решена http://autoit-script.ru/index.php?topic=5810.0;topicseen, а вот с перескоками в Clipmate проблема, контроллировать его фиг знает как, а ежеразно сравнивать данные в разных ячейках не серьезно имея AutoIt под рукой...

А можно ли исключить либо только Clipmate, либо и его и буфер обмена и читать данные поячеечно прямо из Excel'a и вставлять в маску. Можно ли в файле отработанную строку данных помечать, как законченную, что бы строки данных никогда не повторялись и скрипт сам понимал какие данные были успешно обработаны. Может у кого есть примерный код поячеечного копирования данных из Excel'a, который можно было бы модифицировать. Спасибо.
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
valdur2000
Может у кого есть примерный код поячеечного копирования данных из Excel'a, который можно было бы модифицировать
Например:
Код:
$obj = ObjGet('d:\test.xls')
    MsgBox(0, '', $obj.WorkSheets("Лист1").Cells(1, 1).Value)


Кроме того, для работы с Excel существует Excel.au3

Далее,
и есть маска в IE
речь идет о Internet Explorer?
Возможно, в этом вопросе поможет IE.au3 без Mouseclick и ClipGet
На форуме есть примеры заполнения форм.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Возможно, в этом вопросе поможет IE.au3 без Mouseclick и ClipGet
На форуме есть примеры заполнения форм.
SunAwtCanvas прячет все поля, как в бетон. кроме mouseclick ничего не помогло...


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

Код:
Dim $obj
$obj = ObjGet('d:\test.xls')
    MsgBox(0, '', $obj.WorkSheets("Tabelle1").Cells(1, 1).Value)

выдает ошибку:
>Running:(3.3.6.1):C:\Program Files\AutoIt3\autoit3.exe "C:\test.au3"
C:\test.au3 (3) : ==> Variable must be of type "Object".:
MsgBox(0, '', $obj.WorkSheets("Tabelle1").Cells(1, 1).Value)
MsgBox(0, '', $obj^ ERROR
->20:25:02 AutoIT3.exe ended.rc:1
>Exit code: 1 Time: 2.547

Excel 2007 немецкий, в А1 цифра 1.
 

madmasles

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

$s_FilePath = @ScriptDir & '\test.xls';файл Excel
$f_Visible = 0 ; 0 - в скрытом режиме, 1 - в открытом
$i_Sheet = 1 ; номер листа
$i_StartRow = 3 ;номер начальной строки
$i_StartColumn = 3 ;номер начальной колонки (3 - С)
$i_RowCnt = 0 ; 0 - строки считаем до последней заполненной ячейки, если не 0, то см. ниже
$i_ColCnt = 10 ;кол-во колонок, если 0, то см. выше
$o_Excel = _ExcelBookOpen($s_FilePath, $f_Visible)
If @error Then
	MsgBox(16, 'Error', @error)
	Exit
EndIf
_ExcelSheetActivate($o_Excel, $i_Sheet)
If @error Then
	_ExcelBookClose($o_Excel)
	MsgBox(16, 'Error', @error)
	Exit
EndIf
$a_ReturnArray = _ExcelReadSheetToArray($o_Excel, $i_StartRow, $i_StartColumn, $i_RowCnt, $i_ColCnt)
If @error Then
	_ExcelBookClose($o_Excel)
	MsgBox(16, 'Error', @error)
	Exit
EndIf
_ExcelBookClose($o_Excel)
_ArrayDisplay($a_ReturnArray)

For $i = 1 To $a_ReturnArray[0][0]
	For $j = 1 To $a_ReturnArray[0][1]
		MsgBox(64, $i & 'x' & $j, $a_ReturnArray[$i][$j])
		;здесь делайте с этими данными то, что Вам надо
	Next
Next
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Код:
$s_FilePath = @ScriptDir & 'D:\test.xls';файл Excel
$f_Visible = 1 ; 0 - в скрытом режиме, 1 - в открытом
$i_Sheet = 1 ; номер листа
$i_StartRow = 1 ;номер начальной строки
$i_StartColumn = 1 ;номер начальной колонки (3 - С)
$i_RowCnt = 3 ; 0 - строки считаем до последней заполненной ячейки, если не 0, то см. ниже
$i_ColCnt = 6 ;кол-во колонок, если 0, то см. выше
$o_Excel = _ExcelBookOpen($s_FilePath, $f_Visible)
If @error Then
    MsgBox(16, 'Error', @error)
    Exit
EndIf

_ExcelBookOpen выдает ошибку номер 2 - Файл не существует или имеет неправильный формат.
Я создал test.xls (Excel 2003) и test.xlsx (Excel 2007), в коде соответственно менял пути, положил на D в корень... Оставил в файле только одну таблицу с данными, остальные удалил. не получается.
В MsgBox'ah везде поставил разные флаги, что б точно знать какая функция шалит.


Sorry @ScriptDir потер и все заработало. спасибо.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000,
У меня на XP SP3 и Office 2003 все это работает без проблем. Прикрепите пример файла с таблицей, посмотрю.

Это что за бред:
Код:
$s_FilePath = @ScriptDir & 'D:\test.xls'
Посмотрите сами, конечно будет ошибка:
Код:
MsgBox(64, 'Info', @ScriptDir & 'D:\test.xls')
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Еще два вопроса по коду:
теоретически кол-во строк в файле может быть 100000. а можно не генерировать промежуточную таблицу _ArrayDisplay? отключить видимость ее отключил, но если она принципиально не нужна, то можно ли отключить весь процесс генерации?

Код:
For $i = 1 To $a_ReturnArray[0][0]
    For $j = 1 To $a_ReturnArray[0][1]
        ;MsgBox(64, $i & 'x' & $j, $a_ReturnArray[$i][$j])
        ;здесь делайте с этими данными то, что Вам надо
    Next
Next


Код:
MouseClick("left",557,233,1,0)
sleep(200)
Send(ClipGet())
Sleep(200)
MouseClick("left",590,233,1,0)
sleep(200)
Send(ClipGet())
sleep(200)

и таких кусочков по ходу выполнения кода 10 в разных местах. Если не трудно покажите, как состыковать эти два куска кода?

можно ли после успешной отработки строки, поставить метку скажем 1, что б прога ее более никогда не трогала? Спасибо.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000,
Код:
;...
#include <Array.au3>
;...
_ArrayDisplay($a_ReturnArray)
;...
Эти строки можно удалить.
А дальше ничего не понял. Какую строку надо больше не трогать? Что за значения у Вас в буфере обмена?
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
ABCD
1051opel12.01.200234653321
2023VW10.01.200456789902
если поячеечно данные из одной строки были успешно вставлены, то отмечать ее и никогда более не использовать. это нужно для того, что б если отключилось электричество или интернет пропал, знать где закончил. Надеюсь и второй вопрос с объединением двух кодов станет яснее.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Код:
For $i = 1 To $a_ReturnArray[0][0]
    For $j = 1 To $a_ReturnArray[0][1]
        MsgBox(64, $i & 'x' & $j, $a_ReturnArray[$i][$j])
        ;здесь делайте с этими данными то, что Вам надо
    Next
Next

Это кусок кода, присланный madmasles.

А вот, что мне надо делать с данными:
Код:
MouseClick("left",557,233,1,0)
sleep(200)
Send(ClipGet())
Sleep(200)
MouseClick("left",590,233,1,0)
sleep(200)
Send(ClipGet())
sleep(200)

И таких ClipGet'ов до 10 в одном цикле...
Я не понимаю как их объединить в работающую структуру.. Помогите пожалуйста, на примере двух ClipGet'ов, дальше по-логике доделаю. Спасибо.
 

axlwor

Скриптер
Сообщения
657
Репутация
147
Почитай. Может поможет

Что с данными то делать?

ps. код показывает пометочки :rofl: на обработанных данных

Код:
;взято из хелпа
;ошибки не обрабатываются
#include <Excel.au3>
;открываем готовый
;~ $sFilePath = @ScriptDir & "\Test.xls"
;~ $oExcel = _ExcelBookOpen($sFilePath)
;или делаем сами
Make()

If MsgBox(1,0, 'Создали файл Excel. ' & @CRLF & 'Продолжаем?') <> 1 Then
	Exit
EndIf

;~ $oExcel.Application.ScreenUpdating = True
For $s = 1 To $oExcel.ActiveWorkbook.Sheets.Count
	$oExcel.ActiveWorkbook.Sheets($s).Select()
	
	;Если обрабатываем только определенный лист
;~	If $oExcel.ActiveSheet.Name <> 'Твое название листа' Then
;~ 		ContinueLoop
;~	EndIf

	;взято из excel.au3 
	;_ExcelReadSheetToArray
	$sLastCell = $oExcel.Application.Selection.SpecialCells($xlCellTypeLastCell).Address(True, True, $xlR1C1)
	$aLastCell = StringRegExp($sLastCell, "\A[^0-9]*(\d+)[^0-9]*(\d+)\Z", 3)
	$iLastRow = Number($aLastCell[0])
	$iLastColumn = Number($aLastCell[1])
	;Пустые листы пропускаем
	If $sLastCell = "R1C1" And $oExcel.Activesheet.Cells($iLastRow, $iLastColumn).Value = "" Then
		ContinueLoop
	EndIf

	For $r = 1 To $iLastRow
		$sS = ''
		;Заголовок обрабатываем отдельно
		;$iLast - сдвиг по колонке, если поле "обработано" не существует
		If $r = 1 Then
			If $oExcel.Activesheet.Cells($r,  $iLastColumn).Value <> 'Пометка' Then
				_ExcelWriteCell($oExcel, 'Пометка', $r, $iLastColumn + 1)
				$iLast = 1
			Else
				$iLast = 0
			EndIf
			ContinueLoop
		EndIf
		
		;Если последняя колонка "обработано", то пропускаем
		If $oExcel.Activesheet.Cells($r,  $iLastColumn).Value <> 'Обработано' Then
			For $c = 1 To $iLastColumn
				;Здесь делаем то что хотим с данными из excel
				#region Что то будет страаашное
				$sS &= $oExcel.Activesheet.Cells($r,  $c).Value & '|'
				#endregion
			Next
			$oExcel.Activesheet.Cells($r,  $iLastColumn + $iLast).Value = 'Обработано'
		Else
			ContinueLoop
		EndIf
	Next
Next
$oExcel.Application.ScreenUpdating = True
;~ _ExcelBookSave($oExcel)
;~ _ExcelBookClose($oExcel)


Func Make()
	Global $oExcel = _ExcelBookNew()
	;Делаем пустой лист
	_ExcelSheetAddNew($oExcel, 'НазваниеПусто')
	
	;Делаем лист без поля Пометка
	_ExcelSheetAddNew($oExcel, 'НазваниеНоль')
	$MaxRow = Random(20, 30, 1)
	$MaxCol = 1
	_Fill($MaxRow, $MaxCol)

	;Делаем лист с полем Пометка, но без обработано
	_ExcelSheetAddNew($oExcel, 'НазваниеРаз')
	$MaxRow = Random(20, 30, 1)
	$MaxCol = 8
	_Fill($MaxRow, $MaxCol)
	_ExcelWriteCell($oExcel, 'Пометка', 1, $MaxCol + 1)

	;Делаем лист с полем Пометка, и частично обработано
	_ExcelSheetAddNew($oExcel, 'НазваниеДва')
	$MaxRow = Random(20, 30, 1)
	$MaxCol = 5
	_Fill($MaxRow, $MaxCol)
	_ExcelWriteCell($oExcel, 'Пометка', 1, $MaxCol + 1)
	$StartRow = Random(4, 8, 1)
	$Rows = Random($StartRow + 5, $MaxRow - 3)
	For $i = $StartRow To $Rows
		_ExcelWriteCell($oExcel, 'Обработано', $i, $MaxCol + 1)
	Next

	;Делаем лист с полем Пометка, и полностью обработанный
	_ExcelSheetAddNew($oExcel, 'НазваниеТри')
	$MaxRow = Random(20, 30, 1)
	$MaxCol = 10
	_Fill($MaxRow, $MaxCol)
	_ExcelWriteCell($oExcel, 'Пометка', 1, $MaxCol + 1)
	For $i = 2 To $MaxRow
		_ExcelWriteCell($oExcel, 'Обработано', $i, $MaxCol + 1)
	Next


EndFunc

Func _Fill( $iMaxRow, $iMaxCol)
	For $i = 1 To $iMaxRow
		For $j = 1 To $iMaxCol
			If $i = 1 Then
				_ExcelWriteCell($oExcel, 'Колонка' & $j, $i, $j)
			Else
				;Пардон. Под рукой только русский excel
				_ExcelWriteFormula($oExcel, '=СЛУЧМЕЖДУ(1;100)', $i, $j)
			EndIf
		Next
	Next

EndFunc
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Здравствуйте, может и правда я не понятно объясняю, из-за того никто и не отвечает, а я жду, надеюсь, верю... Есть файл Excel'a, в котором ячейки заполнены данным, которые будут вставлены в онлайн маску описания товара (номер, название, дата изготовления, состояние, срок хранения). Данные всегда приходят в xls, и их надо переносить в онлайн базу. на данный момент никаких экспортов-импортов не предусмотрено. только тупое copy paste. в xls в одной строке кол-во данных и их очередность совпадает с кол-вом данных в маске. например 10. и внизу кнопка записать. заполнил-нажал-записалось. Поля очистились, курсор вернулся на поле 1 и страница опять ждет данные. Задача: что б на каждый Send вставлялись данные из следующей ячейки. я запустил скрипт, проходят манипуляции мышки, проверки обновления экрана... курсор попал в текстовое поле, я посылаю Send и туда вставляются данные из A1, затем опять мышка, когда-то опять Send и вставляются данные из А2 и т.д. до А10. потом жмется кнопка подтвердить, скрипт ждет появления первого экрана и запускается все сначала. У меня все работает, но всю таблицу данных из Excel я помещаю вначале в в умную Clipboard программку Clipmate, которая на один send вставляет данные из одной ячейки.

Код:
For $i = 1 To $a_ReturnArray[0][0]
    For $j = 1 To $a_ReturnArray[0][1]
        Send ($a_ReturnArray[$i][$j])
	    MsgBox(64, $i & 'x' & $j, $a_ReturnArray[$i][$j])
	    ;здесь делайте с этими данными то, что Вам надо
    Next
Next

Этот код работает, но постоянно выскакивает MsgBox со значением очередной ячейки и надо жать на ок. А если его заремить, то данные из xls вставляются все сразу. И напишите пожалуйста , как держать данные из очередной ячейки в уме, что б на send вставлять их. А может использовать другой код?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000,
Может я что-то пропустил или не понял, но, ИМХО, вставлять данные в страницу на сайте лучше с помощью функций _IE*.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Там злобный фрейм. ничего не видно. потом я может доберусь до его вскрытия, но пока мышкиных координат и PixelSearch хватает. Узкое место именно получение данных из Excel'a и вставка по Send.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000,
Задайте массив с координатами, заполните его и может так?
Код:
Dim $aCoord[4][2] = [[3],[222, 333],[111, 212],[444, 222]]; и т.д.
$q = 0
For $i = 1 To $a_ReturnArray[0][0]
	For $j = 1 To $a_ReturnArray[0][1]
		If $q = $aCoord[0][0] Then $q = 0
		$q += 1
		MouseClick("left", $aCoord[$q][0], $aCoord[$q][1], 1, 0)
		Sleep(200)
		Send($a_ReturnArray[$i][$j])
		Sleep(500)
	Next
Next
Код не проверял.

valdur2000 [?]
Там злобный фрейм
Дайте ссылку, если она не секретная, или код страницы.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Фрейм за авторизацией. логин сказать не могу. Фреим класса SunAwtCanvas. Сейчас попробую поработать с предложенным вами кодом.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000,
ИМХО, до любого фрейма можно добраться.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
А скажите, a если между вставкой 3 и 4 данными и 6-7 надо сделать только mouseclick на какую-то кнопку, а между 7 - 8 и 9-10 подождать смены страницы и появления цвета pixelgetcolor. Как и где это описать?

Код:
Dim $aCoord[4][2] = [[3],[222, 333],[111, 212],[444, 222]]; и т.д.
$q = 0
For $i = 1 To $a_ReturnArray[0][0]
    For $j = 1 To $a_ReturnArray[0][1]
        If $q = $aCoord[0][0] - 1 Then $q = 0
        $q += 1
        MouseClick("left", $aCoord[$q][0], $aCoord[$q][1], 1, 0)
        Sleep(200)
        Send($a_ReturnArray[$i][$j])
        Sleep(500)
    Next
Next
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000
Дайте скриншот того, куда вставлять данные.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
После каждого Send'a я делаю на всякий случай проверку на появление черного цвета букв по координатам pixelsearch'em, если нет, то опять посылаю туда же Send. Тоже самое с dropdown'ами. До этой страницы кликаю пару раз мышкой, после этой страницы тоже кликаю мышей, жду загрузки PDF Readera, закрываю его,еще в пару полей ставлю данные и заканчиваю цикл. потом заного работа мышью, заполнение этого формуляра, заполнение следующего, закрытие PDF и т.д. Фрейм с левой границы окна, до конца серого цвета.мне б Данные научиться из экселя брать... да вставлять.. Ваш код попробовал, работает, но не совсем.. описал три координаты, а он кликает только на первые две , но вставляет все данные и в правильной последовательности.
 
Верх