Copiar el contenido de un rango a otro, en documentos diferentes

Saludos y muchas bendiciones comunidad.

Quisiera solicitar una ayuda, les comparto mi consulta:
Quiero copiar un rango que se encuentra en una hoja X de un doc X a una hoja Y de un doc Y, ambos abiertos (logre que un documento, de donde se llama la macro, abra al otro, eso me funciona muy bien, puedo abrirlo, guardar los cambios y cerrarlo sin problemas), también sé que estoy en el rango a copiar porque puedo recorrerlo y mostrar el contenido de cada una de sus celdas, sin embargo ahí me quedé.

El rango de la hoja X del doc X, tiene la siguiente estructura:
celda 1
celda 2
celda 3
celda 4

Mientras que el rango de la hoja Y del doc Y, es así:
celda 1 celda 2 celda 3 celda 4

(No pude cargar los capture, porque como soy nueva usuaria, no podía colocar mas de un multimedia o imagen incrustrada)

Yo entiendo que aunque no tengan las mismas dimensiones, una celda del rango de la hoja X del Doc X, tiene su ubicación exacta y precisa en una celda del rango de la hoja Y el Doc Y.

Espero haya podido expresar lo que necesito hacer y agradecería mucho la ayuda y/o sugerencia

Macro en Basic
LibreOffice Version 7.5.2.2
SO Linux 5.4

¿Lo que quieres es transponder los datos?

son varios documentos que deben consolidarse en uno solo :face_in_clouds:
Llamo desde un documento a otro y copio los rangos en su respectiva ubicación.

Si, pero de acuerdo a la estructura que muestras de X y Y, los datos se transponen… ¿es correcto?.. sube un archivo con datos de ejemplo de lo que tienes y lo que esperas…

(@elmau mi respetos y admiración, me he estudiado el libro de arriba hacia abajo y viceversa.)

A lo mejor hacer mi explicación, utilizando X y Y, en vez de Doc1 y Doc2, no fue buena idea.

A continuación archivo de lo que llevo, y estafuncional:

Sub AbriendoFAnzoategui2()

Dim oDoc As Object ’ Doc donde llamo la macro (Consolidado)

Dim sRuta As String
Dim sDato As String
Dim mProps() 'este array no se inicializa pero es necesario definirlo

Dim oDocAbierto As Object '//Documento abierto del ente “FAnzoategui”

Dim oHojas As Object
Dim oHojaAbierta As Object '//Hoja abierta “RESUMEN” del ente “FAnzoategui”
Dim oCelda As Object
Dim oRango As Object
Dim oOrigen As Object
Dim oDestino As Object

Dim oCol As Object
Dim oFil As Object

'**

Dim oHojaOrigen As Object
Dim oHojaDestino As Object

'***
Dim oSel As Object
Dim mDatos
Dim co1 As Long, co2 As Long
Dim Fil As Long, Col As Long

	' Acceso al documento desde donde se llama a esta macro
	oDoc = ThisComponent
	
	sRuta = ConvertToUrl( "/home/usuario/Escritorio/Mincyt-Katryn/Maquetas-prueba/Maqueta_Sistematizacion/Documentos/A0314 F. Anzoategui - MAYO 2023.ods" )
	
	oDocAbierto = StarDesktop.loadComponentFromURL( sRuta, "_blank", 0, mProps() ) 'Documento abierto en MODO VISIBLE

	'Asegurando de que sea una hoja de calculo
	If oDocAbierto.supportsService("com.sun.star.sheet.SpreadsheetDocument") Then

		'Devolvo solo la hoja que me interesa por su nombre.
		oHojaAbierta = oDocAbierto.getSheets.getByName("RESUMEN")
		
		If oHojaAbierta.isProtected Then
			MsgBox "La hoja esta protegida"
		
			'Intentamos desprotegerla
			sDato = Trim( InputBox( "Introduce contraseña" ) )
			oHojaAbierta.unProtect( sDato )
			
			'Verificamos si tuvo éxito la desprotección
			If oHojaAbierta.isProtected Then
				MsgBox "La contraseña no es correcta"
			Else
				MsgBox "Hoja desprotegida correctamente"
			End If
		Else
			MsgBox "La hoja NO esta protegida"
		End If
		
	Else
		MsgBox "No es un documento de hoja de calculo"
	End If

	
	' *** Referencia a un rango de celdas 
	
	'Referencia a "Frecuencia_A0314"
	
	oRango = oHojaAbierta.getCellRangeByName( "Frecuencia_A0314" )

	'Y lo seleccionamos

	oDocAbierto.getCurrentController.select(oRango)
	
            'Una vez seleccionado el Rango
        oSel = oDocAbierto.getCurrentSelection(oRango)

	'**** HICE UNA PRUEBA PARA OBTENER INFORMACION DEL RANGO 
                
		'oDir = oSel.getRangeAddress(oRango)
		
		'Construimos el texto informativo
		'sTmp =	"El rango esta en la hoja: " & oDir.Sheet & Chr(13) & _
		      	'"Columna Inicio: " & oDir.StartColumn & Chr(13) & _
		      	'"Fila Inicio: " & oDir.StartRow & Chr(13) & _
              	'"Columna Fin: " & oDir.EndColumn & Chr(13) & _
             	 '"Fila Fin: " & oDir.EndRow
			 	' MsgBox sTmp
				
		'***Filas y columnas del rango
		'MsgBox "Filas = " & oSel.getRows().getCount() & Chr(13) & _
				' "Columnas = " & oSel.getColumns().getCount()
				
		'***Referencia absoluta de un rango
		'MsgBox oSel.AbsoluteName		

		      
		If oSel.getImplementationName() = "ScCellRangeObj" Then
			
			mDatos = oSel.getDataArray()  '** Para obtener el contenido sea cual sea
			
			'Obtenemos el número de filas y columnas
			Fil = oSel.getRows.getCount() - 1
			Col = oSel.getColumns.getCount() - 1
				For co1 = 0 To Fil
					For co2 = 0 to Col
					'Es más claro el acceso a la matriz
						MsgBox mDatos (co1) (co2)
	                                     '**** Aqui...
					Next
				Next
		End If

	MsgBox "Archivo abierto y modificado correctamente, presione Aceptar para guardar y cerrar"
	
	'Vuelvo a proteger la hoja
	oHojaAbierta.Protect( sDato )
	
	'Guardo los cambios
	oDocAbierto.store()
	
	'Cierro el archivo
	oDocAbierto.close(True)

End Sub

'****( Aquí creo que podría empezar a copiar cada celda a su respectiva celda del otro documento, pero sinceramente estoy bloqueada)

'** Pido disculpas si el código esta un poco desordenado. sobre todo con declaración de variables que no estoy usando aún.

reitero, un archivo con datos (aún tengo la duda si transpones los datos o no) con lo que tienes y lo que esperas obtener es mejor… solo requieres poner las hojas (origen y destino) en el mismo archivo, donde se asume que serían documentos diferentes.

@elmau Saludos!

Si, copio el contenido del rango, de una hoja origen a una hoja destino, los datos del origen debe permanecer, no deben ser borrados.
Me funciono la sugerencia recibida por el compañero @Kyodake, Gracias.
Solo que quisiera primero recorrer el rango origen, y copiar cada celda que lo conforma a su respectiva celda destino.

Si lo que quieres es una macro que copie un rango de celdas especificado en el documento activo (documento en uso) y lo pegue en un documento abierto pero no en uso, cerrando al finalizar el documento abierto pero no en uso, puedes intentar con algo como:

Sub CopiarRangoEntreDocumentos()
    Dim oDoc1 As Object
    Dim oDoc2 As Object
    Dim oSheet1 As Object
    Dim oSheet2 As Object
    Dim oRange1 As Object
    Dim oRange2 As Object
    
    ' Obtener el documento activo (documento en uso)
    oDoc1 = ThisComponent
    
    ' Obtener el documento abierto pero no en uso
    oDoc2 = StarDesktop.loadComponentFromURL("file:///ruta/al/documento2.ods", "_blank", 0, Array())
    
    ' Obtener las hojas de los documentos
    oSheet1 = oDoc1.Sheets(0) ' Hoja de origen (documento en uso)
    oSheet2 = oDoc2.Sheets(0) ' Hoja de destino (documento abierto)
    
    ' Definir el rango de celdas a copiar en la hoja de origen (A1:B5 como ejemplo)
    oRange1 = oSheet1.getCellRangeByName("A1:B5")
    
    ' Obtener la última fila y columna del rango
    Dim lastRow As Long
    Dim lastColumn As Integer
    
    lastRow = oRange1.RangeAddress.EndRow
    lastColumn = oRange1.RangeAddress.EndColumn
    
    ' Definir el rango de destino en la hoja de destino (documento abierto)
    oRange2 = oSheet2.getCellRangeByPosition(0, 0, lastColumn, lastRow)
    
    ' Copiar el contenido del rango de origen al rango de destino
    oRange2.setDataArray(oRange1.getDataArray())
    
    ' Cerrar el documento abierto pero no en uso
    oDoc2.Close(True)
End Sub

Tendrías que reemplazar “file:///ruta/al/documento2.ods” con la ruta y el nombre del archivo del documento abierto en el que deseas pegar el rango de celdas.

1 Like

Agradecida, estoy adaptándolo a ver si es una alternativa.

Sabes amigo @Kyodake , es lo contrario, desde donde activo la macro (documento en uso) voy a abrir otro documento (documento abierto, llamemos), seleccionar un rango, y pegarlo en el documento uso, hice las modificaciones pero no logro que se ejecute correctamente.

@kcos14 : Para copiar un rango de celdas especificado desde un documento donde no se pueden ejecutar macros, (sería no activo) y pegarlo en un documento donde si se pueden ejecutar macros (sería abierto en uso) puedes utilizar el siguiente código:

Sub CopiarRangoDesdeDocumentoNoActivo()
    Dim oDoc1 As Object
    Dim oDoc2 As Object
    Dim oSheet1 As Object
    Dim oSheet2 As Object
    Dim oRange1 As Object
    Dim oRange2 As Object
    
    ' Obtener el documento activo (documento en uso)
    oDoc1 = ThisComponent
    
    ' Obtener el documento no activo
    oDoc2 = StarDesktop.loadComponentFromURL("file:///ruta/al/documento2.ods", "_blank", 0, Array())
    
    ' Obtener las hojas de los documentos
    oSheet1 = oDoc1.Sheets(0) ' Hoja de destino (documento en uso)
    oSheet2 = oDoc2.Sheets(0) ' Hoja de origen (documento no en uso)
    
    ' Definir el rango de celdas a copiar en la hoja de origen (documento no en uso)
    oRange1 = oSheet2.getCellRangeByName("A1:B5")
    
    ' Obtener la última fila y columna del rango
    Dim lastRow As Long
    Dim lastColumn As Integer
    
    lastRow = oRange1.RangeAddress.EndRow
    lastColumn = oRange1.RangeAddress.EndColumn
    
    ' Definir el rango de destino en la hoja de destino (documento en uso)
    oRange2 = oSheet1.getCellRangeByPosition(0, 0, lastColumn, lastRow)
    
    ' Copiar el contenido del rango de origen al rango de destino
    oRange2.setDataArray(oRange1.getDataArray())
    
    ' Cerrar el documento no activo
    oDoc2.Close(True)
End Sub

El código obtendría el documento activo (en uso) que permite ejecutar macros y el documento no activo (no en uso) donde no se permite ejecutar macros, define las hojas correspondientes en cada documento y copia el rango especificado desde la hoja del documento no activo al rango de la hoja del documento en uso.

Reemplaza “file:///ruta/al/documento2.ods” con la ruta adecuada al documento no activo que deseas abrir y copiar desde.
Ajusta el rango de celdas a copiar en la línea:
oRange1 = oSheet2.getCellRangeByName(“A1:B5”)
para adaptarlo a tus necesidades.

Solución encontrada.

@Kyodake sin embargo, comento los inconvenientes que me conseguí, los rangos aunque tienen las mismas celdas, su estructura en cuanto a filas y columnas, no son las mismas, es decir, dimensiones diferentes, por lo que no se logra la copia entre rangos.
Rango 1 de Hoja Origen, tiene la siguiente estructura:
Celda1
Celda2
Celda3
Celda4
Rango 2 de Hoja Destino, tiene la siguiente estructura:
WhatsApp Image 2023-06-30 at 11.51.47 AM

Por consiguiente, quisiera una orientación, en cuanto a la manera en que pueda recorrer el Rango 1 (Hoja Origen), celda por celda, y copiar a su respectiva ubicación dentro del Rango 2 (Hoja destino).

Gracias de antemano. :heart_hands:

solo lo diré una vez más: un archivo con datos de lo que tienes y lo que esperas obtener, ayudará a ayudarte mejor.

1 Like

@kcos14 , además de compartir lo expresado por @elmau , puede que:
Si lo que quieres es copiar los datos y el formato de una serie de celdas de una hoja de un documento a otra serie de celdas en otro documento, por ejemplo de docu1.ods A2:A5 a docu2.ods B2:E2, es más sencillo si utilizas este código:

Editado: para descartar copyTo inexistente

Sub CopiarCeldas()
    Dim oDocOrigen As Object
    Dim oHojaOrigen As Object
    Dim oCeldaOrigen As Object
    Dim oDocDestino As Object
    Dim oHojaDestino As Object
    Dim oCeldaDestino As Object
    
    ' Abrir el documento de origen
    oDocOrigen = StarDesktop.loadComponentFromURL("file:///ruta/docu1.ods", "_blank", 0, Array())
    oHojaOrigen = oDocOrigen.getSheets().getByIndex(0)  ' Obtener la primera hoja del documento de origen
    
    ' Abrir el documento de destino
    oDocDestino = StarDesktop.loadComponentFromURL("file:///ruta/docu2.ods", "_blank", 0, Array())
    oHojaDestino = oDocDestino.getSheets().getByIndex(0)  ' Obtener la primera hoja del documento de destino
    
    ' Copiar los datos y el formato de las celdas
    oCeldaOrigen = oHojaOrigen.getCellRangeByName("A2:A5")  ' Rango de celdas de origen
    oCeldaDestino = oHojaDestino.getCellRangeByName("B2:E2")  ' Rango de celdas de destino
    
    ' Copiar los valores y formatos
    oCeldaDestino.setDataArray(oCeldaOrigen.getDataArray())
    oCeldaDestino.CharWeight = oCeldaOrigen.CharWeight
    oCeldaDestino.CharHeight = oCeldaOrigen.CharHeight
    
    ' Cerrar los documentos
    oDocOrigen.close(True)
    oDocDestino.close(True)
End Sub

Tienes que reemplazar “file:///ruta/docu1.ods” y “file:///ruta/docu2.ods” con las rutas correctas de los documentos docu1.ods y docu2.ods, respectivamente.

1 Like

Gracias por todo el apoyo. Ha sido muy amable y considerado. :heart_hands:

¿Seguro que existe el método “copyTo”?

image