Что нового

Excel копирование листа между двумя файлами

AlexVong

Новичок
Сообщения
112
Репутация
1
Подскажите как скопировать целиком лист из одной книги в другую с сохранение всех данных и имени листа?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
AlexVong,
Попробуйте примерно так, у меня в Excel 2003 работает (только если $sFileTo не открыт).
Код:
#include <Excel.au3>

Local $sFileFrom = @ScriptDir & '\From.xls', $sFileTo = @ScriptDir & '\To.xls', $oExcel

$oExcel = _ExcelBookOpen($sFileFrom);, 0)
$oExcel.Sheets(1).Copy($oExcel.Workbooks.Open($sFileTo).Sheets(1))
_ExcelBookClose($oExcel)
Если работает в Excel выше 2003, могу сделать функцию.
 
Автор
A

AlexVong

Новичок
Сообщения
112
Репутация
1
madmasles
Спасибо! ... Отлично работает в Excel 2010.

А возможно сделать чтобы закрывалась только одна книга - из которой скопировали лист?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
AlexVong,
Протестируйте, пожалуйста функцию, желательно во всех режимах. У меня на Excel 2003 все работает.
Код:
Opt('MustDeclareVars', 1)

Global $sFileFrom = @ScriptDir & '\From.xls', $sFileTo = @ScriptDir & '\To.xls', $sRet

$sRet = _ExcelSheetCopyToOtherFile($sFileFrom, $sFileTo, 'ТЕСТ')
ConsoleWrite($sRet & @TAB & @extended & @TAB & @error & @LF)

#cs
	Копирует лист Excel в другой файл Excel с тем же именем. Оба файла (или любой из них) могут быть открыты или закрыты.

	$s_FileFrom			- полный путь к файлу Excel из которого будет копироваться лист;
	$s_FileTo			- полный путь к файлу Excel куда будет копироваться лист;
	$v_SheetFrom		- имя (не зависит от регистра) или номер копируемого листа;
	$v_SheetTo			- имя (не зависит от регистра) или номер листа в $s_FileTo до или после которого будет скопирован $v_SheetFrom,
	;					  по умолчанию (-1 или Default) будет скопирован в конец, не зависимо от $f_After.
	;					  Если такого листа нет в $s_FileTo, то лист $v_SheetFrom будет скопирован в конец, не зависимо от $f_After.
	$f_CloseFrom		- Закрыть $s_FileFrom после копирования листа, по умолчанию закрыть (не 0 или True);
	$f_CloseTo			- Закрыть $s_FileTo после копирования листа, по умолчанию закрыть (не 0 или True);
	$f_After			- до (0 или False) или после (не 0 или True) $v_SheetTo поместить лист $v_SheetFrom, по умолчанию - после (True)
	$s_PassFrom			- Пароль к защищенному паролем $s_FileFrom, по умолчанию нет пароля ('');
	$s_WritePassFrom	- Пароль защиты от редактирования в $s_FileFrom, по умолчанию нет пароля ('');
	$s_PassTo			- Пароль к защищенному паролем $s_FileTo, по умолчанию нет пароля ('');
	$s_WritePassTo		- Пароль защиты от редактирования в $s_FileTo, по умолчанию нет пароля ('');
	$s_PassProtectTo	- Пароль защиты от изменения структуры $s_FileTo, по умолчанию нет пароля ('').

	При успехе вернет имя скопированного листа в файле $s_FileTo и флаг @extended - его номер.

	При неудаче '', флаг @extended = 0 и флаг @error = :
	1					- файла $s_FileFrom не существует;
	2					- файла $s_FileTo не существует;
	3					- ошибка создания объекта-обработчика ошибок;
	4					- ошибка создания(получения) объекта Excel.Application;
	5					- файл $s_FileTo уже открыт в режиме только для чтения (ReadOnly);
	6					- ошибка открытия файла $s_FileFrom (99% не правильные пароли $s_PassFrom или $s_WritePassFrom);
	7					- ошибка открытия файла $s_FileTo (99% не правильные пароли $s_PassTo или $s_WritePassTo);
	8					- ошибка снятия защиты от изменения структуры $s_FileTo (99% не правильный пароль $s_PassProtectTo);
	9					- листа с именем или номером $v_SheetFrom нет в $s_FileFrom;
	10					- ошибка получения объекта листа в $s_FileTo до или после которого будет скопирован $v_SheetFrom;
	11					- ошибка копирования листа;
	12					- ошибка сохранения изменений в $s_FileTo;
	13					- ошибка сохранения изменений в $s_FileFrom;
	14					- ошибка закрытия $s_FileFrom;
	15					- ошибка закрытия $s_FileTo;
#ce
Func _ExcelSheetCopyToOtherFile($s_FileFrom, $s_FileTo, $v_SheetFrom, $v_SheetTo = Default, $f_CloseFrom = True, $f_CloseTo = True, $f_After = True, _
		$s_PassFrom = '', $s_WritePassFrom = '', $s_PassTo = '', $s_WritePassTo = '', $s_PassProtectTo = '')

	Local $i_Error, $o_Excel, $o_Error, $f_Exist, $o_TmpObjs, $o_From, $o_To, $o_ToSheets, $i_Num, $i_CountTo, $s_Name

	If Not FileExists($s_FileFrom) Then Return SetError(1, 0, 0)
	If Not FileExists($s_FileTo) Then Return SetError(2, 0, 0)
	If Not ObjEvent('AutoIt.Error') Then
		$o_Error = ObjEvent('AutoIt.Error', '_ExcelSheetCopyToOtherFile')
		If Not IsObj($o_Error) Then Return SetError(3, 0, 0)
	EndIf
	$o_Excel = ObjGet('', 'Excel.Application')
	If IsObj($o_Excel) Then
		$f_Exist = True
	Else
		$o_Excel = ObjCreate('Excel.Application')
		If (Not $f_CloseFrom) Or (Not $f_CloseTo) Then
			$o_Excel.Visible = True
		EndIf
	EndIf
	If Not IsObj($o_Excel) Then Return SetError(4, 0, 0)
	$o_Excel.Application.DisplayAlerts = False
	$o_Excel.Application.ScreenUpdating = False
	Do
		If $f_Exist Then
			$o_TmpObjs = $o_Excel.Application.Workbooks
			For $o_TmpObj In $o_TmpObjs
				If $o_TmpObj.FullName = $s_FileFrom Then
					If $o_TmpObj.ReadOnly Then $f_CloseFrom = False
					$o_From = $o_TmpObj
				EndIf
				If $o_TmpObj.FullName = $s_FileTo Then
					If $o_TmpObj.ReadOnly Then
						$i_Error = 5
						ExitLoop 2
					EndIf
					$o_To = $o_TmpObj
				EndIf
			Next
		EndIf
		$o_TmpObjs = 0
		If Not IsObj($o_From) Then
			$o_From = $o_Excel.Workbooks.Open($sFileFrom, Default, False, Default, $s_PassFrom, $s_WritePassFrom)
			If Not IsObj($o_From) Then
				$i_Error = 6
				ExitLoop
			EndIf
		EndIf
		If Not IsObj($o_To) Then
			$o_To = $o_Excel.Workbooks.Open($s_FileTo, Default, False, Default, $s_PassTo, $s_WritePassTo)
			If Not IsObj($o_To) Then
				$i_Error = 7
				ExitLoop
			EndIf
			If $o_To.ProtectStructure Then
				$o_To.UnProtect($s_PassProtectTo)
				If $o_To.ProtectStructure Then
					$i_Error = 8
					ExitLoop
				EndIf
			EndIf
		EndIf
		$o_From = $o_From.Sheets($v_SheetFrom)
		If Not IsObj($o_From) Then
			$i_Error = 9
			ExitLoop
		EndIf
		$o_ToSheets = $o_To.Sheets
		$i_CountTo = $o_ToSheets.Count
		$o_TmpObjs = $o_ToSheets($v_SheetTo)
		If IsObj($o_TmpObjs) Then
			$o_To = $o_TmpObjs
		Else
			$o_To = $o_ToSheets($i_CountTo)
			$f_After = True
		EndIf
		If Not IsObj($o_To) Then
			$i_Error = 10
			ExitLoop
		EndIf
		$i_Num = $o_To.Index
		$o_TmpObjs = 0
		If $f_After Then
			$o_From.Copy(Default, $o_To)
			$i_Num += 1
		Else
			$o_From.Copy($o_To)
		EndIf
		If $o_ToSheets.Count - $i_CountTo <> 1 Then
			$i_Error = 11
			ExitLoop
		EndIf
		$s_Name = $o_ToSheets($i_Num).Name
		$o_To = $o_To.Parent
		If Not $o_To.Save Then
			$i_Error = 12
			ExitLoop
		EndIf
		If $f_CloseFrom Then
			$o_From = $o_From.Parent
			If Not $o_From.Saved Then
				If Not $o_From.Save Then
					$i_Error = 13
					ExitLoop
				EndIf
			EndIf
			If Not $o_From.Close Then
				$i_Error = 14
				ExitLoop
			EndIf
		Else
			If Not $o_Excel.Visible Then $o_Excel.Visible = True
		EndIf
		If $f_CloseTo Then
			If Not $o_To.Close Then
				$i_Error = 15
				ExitLoop
			EndIf
		Else
			If Not $o_Excel.Visible Then $o_Excel.Visible = True
		EndIf
		$i_Error = 0
	Until 1
	$o_Excel.Application.DisplayAlerts = True
	$o_Excel.Application.ScreenUpdating = True
	If $i_Error Then
		If Not $o_Excel.Visible Then $o_Excel.Visible = True
	Else
		If Not $o_Excel.Application.Workbooks.Count Then $o_Excel.Quit
	EndIf
	Return SetError($i_Error, $i_Num, $s_Name)
EndFunc   ;==>_ExcelSheetCopyToOtherFile
 
Автор
A

AlexVong

Новичок
Сообщения
112
Репутация
1
madmasles
Excel 2010 - работает на УРА!
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
AlexVong,
Окончательный, исправленный, вариант функции _ExcelSheetCopyToOtherFile.
Код:
#cs
	Копирует лист Excel в другой файл Excel с тем же именем. Оба файла (или любой из них) могут быть открыты или закрыты.

	$s_FileFrom			- полный путь к файлу Excel из которого будет копироваться лист;
	$s_FileTo			- полный путь к файлу Excel куда будет копироваться лист;
	$v_SheetFrom		- имя (не зависит от регистра) или номер копируемого листа;
	$v_SheetTo			- имя (не зависит от регистра) или номер листа в $s_FileTo до или после которого будет скопирован $v_SheetFrom,
	;					  по умолчанию (-1 или Default) будет скопирован в конец, не зависимо от $f_After.
	;					  Если такого листа нет в $s_FileTo, то лист $v_SheetFrom будет скопирован в конец, не зависимо от $f_After.
	$f_CloseFrom		- Закрыть $s_FileFrom после копирования листа, по умолчанию закрыть (не 0 или True);
	$f_CloseTo			- Закрыть $s_FileTo после копирования листа, по умолчанию закрыть (не 0 или True);
	$f_After			- до (0 или False) или после (не 0 или True) $v_SheetTo поместить лист $v_SheetFrom, по умолчанию - после (True)
	$s_PassFrom			- Пароль к защищенному паролем $s_FileFrom, по умолчанию нет пароля ('');
	$s_WritePassFrom	- Пароль защиты от редактирования в $s_FileFrom, по умолчанию нет пароля ('');
	$s_PassTo			- Пароль к защищенному паролем $s_FileTo, по умолчанию нет пароля ('');
	$s_WritePassTo		- Пароль защиты от редактирования в $s_FileTo, по умолчанию нет пароля ('');
	$s_PassProtectTo	- Пароль защиты от изменения структуры $s_FileTo, по умолчанию нет пароля ('').

	При успехе вернет имя скопированного листа в файле $s_FileTo и флаг @extended - его номер.

	При неудаче '', флаг @extended = 0 и флаг @error = :
	1					- файла $s_FileFrom не существует;
	2					- файла $s_FileTo не существует;
	3					- ошибка создания объекта-обработчика ошибок;
	4					- ошибка создания(получения) объекта Excel.Application;
	5					- файл $s_FileTo открыт в режиме только для чтения (ReadOnly);
	6					- ошибка открытия файла $s_FileFrom (99% не правильные пароли $s_PassFrom или $s_WritePassFrom);
	7					- ошибка открытия файла $s_FileTo (99% не правильные пароли $s_PassTo или $s_WritePassTo);
	8					- ошибка снятия защиты от изменения структуры(окна) $s_FileTo (99% не правильный пароль $s_PassProtectTo);
	9					- листа с именем или номером $v_SheetFrom нет в $s_FileFrom;
	10					- ошибка получения объекта листа в $s_FileTo до или после которого будет скопирован $v_SheetFrom;
	11					- ошибка копирования листа;
	12					- ошибка установки защиты от изменения структуры(окна) $s_FileTo (если была установлена);
	13					- ошибка сохранения изменений в $s_FileTo;
	14					- ошибка сохранения изменений в $s_FileFrom;
	15					- ошибка закрытия $s_FileFrom;
	16					- ошибка закрытия $s_FileTo;
#ce
Func _ExcelSheetCopyToOtherFile($s_FileFrom, $s_FileTo, $v_SheetFrom, $v_SheetTo = Default, $f_CloseFrom = True, $f_CloseTo = True, $f_After = True, _
		$s_PassFrom = '', $s_WritePassFrom = '', $s_PassTo = '', $s_WritePassTo = '', $s_PassProtectTo = '')

	Local $i_Error, $o_Error, $a_Excel[3], $a_From[2], $a_To[4], $a_Ret[3]

	If Not FileExists($s_FileFrom) Then Return SetError(1, 0, 0)
	If Not FileExists($s_FileTo) Then Return SetError(2, 0, 0)
	If Not ObjEvent('AutoIt.Error') Then
		$o_Error = ObjEvent('AutoIt.Error', '_ExcelSheetCopyToOtherFile')
		If Not IsObj($o_Error) Then Return SetError(3, 0, 0)
	EndIf
	$a_Excel[0] = ObjGet('', 'Excel.Application')
	If IsObj($a_Excel[0]) Then
		$a_Excel[2] = True
	Else
		$a_Excel[0] = ObjCreate('Excel.Application')
		If (Not $f_CloseFrom) Or (Not $f_CloseTo) Then
			$a_Excel[0] .Visible = True
		EndIf
	EndIf
	If Not IsObj($a_Excel[0]) Then Return SetError(4, 0, 0)
	$a_Excel[0] .Application.DisplayAlerts = False
	$a_Excel[0] .Application.ScreenUpdating = False
	Do
		If $a_Excel[2] Then
			$a_Excel[1] = $a_Excel[0] .Application.Workbooks
			For $o_Tmp In $a_Excel[1]
				If $o_Tmp.FullName = $s_FileFrom Then
					If $o_Tmp.ReadOnly Then $f_CloseFrom = False
					$a_From[0] = $o_Tmp
				EndIf
				If $o_Tmp.FullName = $s_FileTo Then
					If $o_Tmp.ReadOnly Then
						$i_Error = 5
						ExitLoop 2
					EndIf
					$a_To[0] = $o_Tmp
				EndIf
			Next
		EndIf
		$a_Excel[1] = 0
		If Not IsObj($a_From[0]) Then
			$a_From[0] = $a_Excel[0] .Workbooks.Open($sFileFrom, Default, False, Default, $s_PassFrom, $s_WritePassFrom)
			If Not IsObj($a_From[0]) Then
				$i_Error = 6
				ExitLoop
			EndIf
		EndIf
		If Not IsObj($a_To[0]) Then
			$a_To[0] = $a_Excel[0] .Workbooks.Open($s_FileTo, Default, False, Default, $s_PassTo, $s_WritePassTo, True)
		EndIf
		If Not IsObj($a_To[0]) Then
			$i_Error = 7
			ExitLoop
		EndIf
		If $a_To[0] .ReadOnly Then
			$i_Error = 5
			ExitLoop
		EndIf
		$a_To[2] = $a_To[0] .ProtectStructure
		If $a_To[2] Then
			$a_To[3] = $a_To[0] .ProtectWindows
			$a_To[0] .UnProtect($s_PassProtectTo)
			If $a_To[0] .ProtectStructure Then
				$i_Error = 8
				ExitLoop
			EndIf
		EndIf
		$a_From[1] = $a_From[0] .Sheets($v_SheetFrom)
		If Not IsObj($a_From[1]) Then
			$i_Error = 9
			ExitLoop
		EndIf
		$a_Ret[0] = $a_To[0] .Sheets.Count
		$a_To[1] = $a_To[0] .Sheets($v_SheetTo)
		If Not IsObj($a_To[1]) Then
			$a_To[1] = $a_To[0] .Sheets($a_Ret[0])
			$f_After = True
		EndIf
		If Not IsObj($a_To[1]) Then
			$i_Error = 10
			ExitLoop
		EndIf
		$a_Ret[1] = $a_To[1] .Index
		If $f_After Then
			$a_From[1] .Copy(Default, $a_To[1])
			$a_Ret[1] += 1
		Else
			$a_From[1] .Copy($a_To[1])
		EndIf
		If $a_To[0] .Sheets.Count - $a_Ret[0] <> 1 Then
			$i_Error = 11
			ExitLoop
		EndIf
		$a_Ret[2] = $a_To[0] .Sheets($a_Ret[1]).Name
		If $a_To[2] Then
			$a_To[0] .Protect($s_PassProtectTo, $a_To[2], $a_To[3])
			If ($a_To[0] .ProtectStructure <> $a_To[2]) Or ($a_To[0] .ProtectWindows <> $a_To[3]) Then
				$i_Error = 12
				ExitLoop
			EndIf
		EndIf
		If Not $a_To[0] .Save Then
			$i_Error = 13
			ExitLoop
		EndIf
		If $f_CloseFrom Then
			If Not $a_From[0] .Saved Then
				If Not $a_From[0] .Save Then
					$i_Error = 14
					ExitLoop
				EndIf
			EndIf
			If Not $a_From[0] .Close Then
				$i_Error = 15
				ExitLoop
			EndIf
		Else
			If Not $a_Excel[0] .Visible Then $a_Excel[0] .Visible = True
		EndIf
		If $f_CloseTo Then
			If Not $a_To[0] .Close Then
				$i_Error = 16
				ExitLoop
			EndIf
		Else
			If Not $a_Excel[0] .Visible Then $a_Excel[0] .Visible = True
		EndIf
		$i_Error = 0
	Until 1
	$a_Excel[0] .Application.DisplayAlerts = True
	$a_Excel[0] .Application.ScreenUpdating = True
	If $i_Error Then
		If Not $a_Excel[0] .Visible Then $a_Excel[0] .Visible = True
	Else
		If Not $a_Excel[0] .Application.Workbooks.Count Then $a_Excel[0] .Quit
	EndIf
	Return SetError($i_Error, $a_Ret[1], $a_Ret[2])
EndFunc   ;==>_ExcelSheetCopyToOtherFile
 

ВиталийВВ

Новичок
Сообщения
176
Репутация
0
madmasles сказал(а):
AlexVong,
Попробуйте примерно так, у меня в Excel 2003 работает (только если $sFileTo не открыт).
Код:
#include <Excel.au3>

Local $sFileFrom = @ScriptDir & '\From.xls', $sFileTo = @ScriptDir & '\To.xls', $oExcel

$oExcel = _ExcelBookOpen($sFileFrom);, 0)
$oExcel.Sheets(1).Copy($oExcel.Workbooks.Open($sFileTo).Sheets(1))
_ExcelBookClose($oExcel)
Если работает в Excel выше 2003, могу сделать функцию.
Пробую этот скрипт, у меня при копировании если нет в To.xls листа 1, то он создается, а если есть, то создается лист с именем 1(2). как сделать, чтоб копировалось в лист именно 1?
 

ra4o

AutoIT Гуру
Сообщения
1 101
Репутация
223
ВиталийВВ, Вы используете функции старого "Excel.au3", с новыми версиями Autoit Ваш пример работать не будет .
если нет в To.xls листа 1, то он создается
Значит, Вы его перед тем, как записать - удаляйте , например, для старой версии "Excel.au3" - это функция
Код:
_ExcelSheetDelete()
, для новой версии - функция
Код:
_Excel_SheetDelete
 

ВиталийВВ

Новичок
Сообщения
176
Репутация
0
ra4o сказал(а):
ВиталийВВ, Вы используете функции старого "Excel.au3", с новыми версиями Autoit Ваш пример работать не будет .
если нет в To.xls листа 1, то он создается
Значит, Вы его перед тем, как записать - удаляйте , например, для старой версии "Excel.au3" - это функция
Код:
_ExcelSheetDelete()
, для новой версии - функция
Код:
_Excel_SheetDelete
А если я удалю лист 1, то что произойдет с формулами, которые опираются на этот лист? Если сделать это руками, то в екселе, формулы сбиваются.
 

ra4o

AutoIT Гуру
Сообщения
1 101
Репутация
223
Пробовали функцию "_ExcelSheetCopyToOtherFile" от madmasles?
 
Верх