Marcos Alberto Rosas Lara
Introducción
Microsoft Excel es la hoja de cálculo más utilizada en el mundo, algunos sitios de dependencias de gobierno como el INEGI, SCT, etc. Nos permiten exportar información en este tipo de archivos, asimismo son muchísimas las empresas y personas que utilizan este programa para guardar sus bases de datos.
De ahí lo importante que conozcamos la manera de importar y exportar información desde R a archivos de Microsoft Excel.
Aunado a la función de exportar información y gráficos a archivos de Excel, se tiene la posibilidad de crear estos archivos y editarlos. El presente trabajo pretende dar una guía rápida en la utilización del paquete XLSX para R.
Requerimientos del sistema
Para poder empezar a utilizar el paquete XLSX en R, se necesita tener previamente instalada la versión de 64 bits de java y los paquetes para R: rJava y xlsxjars.
Instalar xlsx en R
para instalar xlsx se puede utilizar el siguiente comando:
#Instalar paquete xlsx
install.packages("xlsx")
Cargar xlsx en R
Con el fin de evitar posibles mensajes de error se sugiere utilizar los siguientes comandos para cargar xlsx.
#Cargar paquete xlsx
library("rJava")
library("xlsxjars")
library("xlsx")
Leer una hoja de un libro de Excel.
Para poder utilizar la información de una hoja de cálculo, se requiere tener bien estructurada la tabla de datos y que xlsx la pueda leer correctamente, para ello utilizamos la siguiente estructura de comandos que nos permiten importar la información y utilizarla como si se tratara de un data set.
Nombre que se dará a la tabla <- read.xlsx(“nombre y extensión del archivo”, sheeName = Nombre de la hoja del libro de excel, rowIndex= Rango de filas, colIndex= Rango de Columnas)
Ejemplo:
#Abrir Hoja de Excel y leer área de base de datos
Matrimonios <- read.xlsx("Matrim.xlsx", #Nombre de archivo
sheetName = "1995", #Nombre de la hoja
rowIndex = 1:15, #Vector de filas
colIndex= 1:4, #Vector de columnas
header=TRUE) #La primer fila contiene los encabezados
Al ejecutar este comando podemos ya leer la información de la tabla en R e interactuar con los datos en todas las formas que R nos permite.
(Matrimonios)
La tabla nos muestra el numero de personas que se casaron en México en 1995 por edad y sexo.
Se pueden añadir comandos adicionales para definir el área a importar de la hoja de cálculo. En donde los argumentos de los comandos, pueden ser los siguientes:
File: Archivo a leerse
sheetName: Nombre de la hoja en el archivo
sheetIndex: Número de la hoja en el archivo
rowIndex: Vector numérico que indica las filas que desea extraer. Si NULL, todas las filas encontradas se extraerán, a menos que se especifique startRow o endRow
colIndex: Vector numérico que indica las columnas que desea extraer. Si NULL, se extraerán todas las columnas encontradas
as.data.frame: Valor lógico que indica si el resultado debe ser coaccionado en un archivo data.frame. Si FALSE, el resultado es una lista con un elemento para cada columna.
Header: Valor lógico que indica si la primera fila correspondiente al primer elemento del vector rowIndex contiene los nombres de las variables.
ColClasses: Para read.xlsx un vector de caracteres que representa la clase de cada columna. Si el vector de caracteres es nombrado, los valores no especificados se toman como NA.
KeepFormulas: Valor lógico que indica si las fórmulas de Excel deben mostrarse como texto en R y no evaluadas antes de introducirlas.
Encoding: Codificación para las cadenas de entrada.
StartRow: Número que especifica el índice de la fila inicial. Para read.xlsx este argumento sólo está activo si rowIndex es NULL.
EndRow: Número que especifica el índice de la última fila a importar. Si es NULL, lea todas las filas de la hoja. Para read.xlsx este argumento sólo está activo si rowIndex es NULL.
Editar archivos en Excel
Al igual que para extraer la información tenemos que tomarla desde Microsoft Excel, al compartirla se vuelve importarnte el poder hacerlo en este formato de archivo. Para ello xlsx tiene la función de exportar información con el siguiente comando.
write.xlsx(x, file, sheetName="Sheet1",
col.names=TRUE, row.names=TRUE, append=FALSE)
write.xlsx2(x, file, sheetName="Sheet1",
col.names=TRUE, row.names=TRUE, append=FALSE)
En donde los argumentos dados en los comandos, son los siguientes:
X (Marco de datos que se escribirá en el libro)
File (Ruta al archivo de salida)
SheetName (Cadena de caracteres a utilizar para el nombre de la hoja.)
Col.names, row.names (Valor lógico que especifica si los nombres de columnas / nombres de filas de x deben escribirse en el archivo)
Append (Valor lógico que indica si se debe añadir x a un archivo existente)
Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
Principales argumentos
CellRange Cadena que especifica el rango de celdas.
ColIndex Vector numérico que especifica las columnas que desea utilizar en el tamaño automático.
ColSplit Valor numérico para la columna a dividir.
ColWidth Valor numérico para especificar el ancho de la columna. Las unidades están en 1 / 256ths de un ancho de carácter.
Denominador Valor numérico que representa el denomiador de la relación de zoom.
EndColumn Valor numérico para la columna final.
EndRow Valor numérico para la fila final.
Ind Valor numérico que indica la región fusionada que desea eliminar.
Numerator Valor numérico que representa el numerador de la relación de zoom.
Position Caractér. Los valores válidos son "PANE_LOWER_LEFT", "PANE_LOWER_RIGHT", "PANE_UPPER_LEFT", "PANE_UPPER_RIGHT".
RowSplit Valor numérico para la fila para dividir.
Sheet Objeto de hoja de cálculo.
SheetIndex Valor numérico para el índice de hoja de cálculo.
StartColumn Valor numérico para la columna de inicio.
StartRow Valor numérico para la fila de inicio.
XSplitPos Valor numérico para la posición horizontal de split en 1/20 de un punto.
YSplitPos Valor numérico para la posición vertical de split en 1/20 de un punto.
Wb Objeto de libro.
LS0tDQp0aXRsZTogIk1hbnVhbCBi4XNpY28gZGVsIHBhY2thZ2UgWExTWCBwYXJhIFIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyNNYXJjb3MgQWxiZXJ0byBSb3NhcyBMYXJhDQoNCiMjIyNJbnRyb2R1Y2Np824NCg0KTWljcm9zb2Z0IEV4Y2VsIGVzIGxhIGhvamEgZGUgY+FsY3VsbyBt4XMgdXRpbGl6YWRhIGVuIGVsIG11bmRvLCBhbGd1bm9zIHNpdGlvcyBkZSBkZXBlbmRlbmNpYXMgZGUgZ29iaWVybm8gY29tbyBlbCBJTkVHSSwgU0NULCBldGMuIE5vcyBwZXJtaXRlbiBleHBvcnRhciBpbmZvcm1hY2nzbiBlbiBlc3RlIHRpcG8gZGUgYXJjaGl2b3MsIGFzaW1pc21vIHNvbiBtdWNo7XNpbWFzIGxhcyBlbXByZXNhcyB5IHBlcnNvbmFzIHF1ZSB1dGlsaXphbiBlc3RlIHByb2dyYW1hIHBhcmEgZ3VhcmRhciBzdXMgYmFzZXMgZGUgZGF0b3MuDQoNCkRlIGFo7SBsbyBpbXBvcnRhbnRlIHF1ZSBjb25vemNhbW9zIGxhIG1hbmVyYSBkZSBpbXBvcnRhciB5IGV4cG9ydGFyIGluZm9ybWFjafNuIGRlc2RlIFIgYSBhcmNoaXZvcyBkZSBNaWNyb3NvZnQgRXhjZWwuDQoNCkF1bmFkbyBhIGxhIGZ1bmNp824gZGUgZXhwb3J0YXIgaW5mb3JtYWNp824geSBncuFmaWNvcyBhIGFyY2hpdm9zIGRlIEV4Y2VsLCBzZSB0aWVuZSBsYSBwb3NpYmlsaWRhZCBkZSBjcmVhciBlc3RvcyBhcmNoaXZvcyB5IGVkaXRhcmxvcy4NCkVsIHByZXNlbnRlIHRyYWJham8gcHJldGVuZGUgZGFyIHVuYSBnde1hIHLhcGlkYSBlbiBsYSB1dGlsaXphY2nzbiBkZWwgcGFxdWV0ZSBYTFNYIHBhcmEgUi4NCg0KIyMjI1JlcXVlcmltaWVudG9zIGRlbCBzaXN0ZW1hDQoNClBhcmEgcG9kZXIgZW1wZXphciBhIHV0aWxpemFyIGVsIHBhcXVldGUgWExTWCBlbiBSLCBzZSBuZWNlc2l0YSB0ZW5lciBwcmV2aWFtZW50ZSBpbnN0YWxhZGEgbGEgdmVyc2nzbiBkZSA2NCBiaXRzIGRlIGphdmEgeSBsb3MgcGFxdWV0ZXMgcGFyYSBSOiBySmF2YSB5IHhsc3hqYXJzLg0KDQojIyMjSW5zdGFsYXIgeGxzeCBlbiBSDQpwYXJhIGluc3RhbGFyIHhsc3ggc2UgcHVlZGUgdXRpbGl6YXIgZWwgc2lndWllbnRlIGNvbWFuZG86DQoNCmBgYHtyfQ0KI0luc3RhbGFyIHBhcXVldGUgeGxzeA0KaW5zdGFsbC5wYWNrYWdlcygieGxzeCIpDQpgYGANCg0KDQojIyMjQ2FyZ2FyIHhsc3ggZW4gUg0KQ29uIGVsIGZpbiBkZSBldml0YXIgcG9zaWJsZXMgbWVuc2FqZXMgZGUgZXJyb3Igc2Ugc3VnaWVyZSB1dGlsaXphciBsb3Mgc2lndWllbnRlcyBjb21hbmRvcyBwYXJhIGNhcmdhciB4bHN4Lg0KDQpgYGB7cn0NCiNDYXJnYXIgcGFxdWV0ZSB4bHN4DQpsaWJyYXJ5KCJySmF2YSIpDQpsaWJyYXJ5KCJ4bHN4amFycyIpDQpsaWJyYXJ5KCJ4bHN4IikNCmBgYA0KDQogDQoNCiMjIyNMZWVyIHVuYSBob2phIGRlIHVuIGxpYnJvIGRlIEV4Y2VsLg0KDQpQYXJhIHBvZGVyIHV0aWxpemFyIGxhIGluZm9ybWFjafNuIGRlIHVuYSBob2phIGRlIGPhbGN1bG8sIHNlIHJlcXVpZXJlIHRlbmVyIGJpZW4gZXN0cnVjdHVyYWRhIGxhIHRhYmxhIGRlIGRhdG9zIHkgcXVlIHhsc3ggbGEgcHVlZGEgbGVlciBjb3JyZWN0YW1lbnRlLCBwYXJhIGVsbG8gdXRpbGl6YW1vcyBsYSBzaWd1aWVudGUgZXN0cnVjdHVyYSBkZSBjb21hbmRvcyBxdWUgbm9zIHBlcm1pdGVuIGltcG9ydGFyIGxhIGluZm9ybWFjafNuIHkgdXRpbGl6YXJsYSBjb21vIHNpIHNlIHRyYXRhcmEgZGUgdW4gZGF0YSBzZXQuDQoNCg0KTm9tYnJlIHF1ZSBzZSBkYXLhIGEgbGEgdGFibGEgPC0gcmVhZC54bHN4KCJub21icmUgeSBleHRlbnNp824gZGVsIGFyY2hpdm8iLCBzaGVlTmFtZSA9IE5vbWJyZSBkZSBsYSBob2phIGRlbCBsaWJybyBkZSBleGNlbCwgcm93SW5kZXg9IFJhbmdvIGRlIGZpbGFzLCBjb2xJbmRleD0gUmFuZ28gZGUgQ29sdW1uYXMpDQoNCkVqZW1wbG86DQoNCmBgYHtyfQ0KI0FicmlyIEhvamEgZGUgRXhjZWwgeSBsZWVyIOFyZWEgZGUgYmFzZSBkZSBkYXRvcw0KTWF0cmltb25pb3MgPC0gcmVhZC54bHN4KCJNYXRyaW0ueGxzeCIsICNOb21icmUgZGUgYXJjaGl2bw0KICAgICAgICAgICAgICAgICAgICAgICAgIHNoZWV0TmFtZSA9ICIxOTk1IiwgI05vbWJyZSBkZSBsYSBob2phDQogICAgICAgICAgICAgICAgICAgICAgICAgcm93SW5kZXggPSAxOjE1LCAjVmVjdG9yIGRlIGZpbGFzDQogICAgICAgICAgICAgICAgICAgICAgICAgY29sSW5kZXg9IDE6NCwgI1ZlY3RvciBkZSBjb2x1bW5hcw0KICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcj1UUlVFKSAjTGEgcHJpbWVyIGZpbGEgY29udGllbmUgbG9zIGVuY2FiZXphZG9zDQpgYGANCg0KIA0KQWwgZWplY3V0YXIgZXN0ZSBjb21hbmRvIHBvZGVtb3MgeWEgbGVlciBsYSBpbmZvcm1hY2nzbiBkZSBsYSB0YWJsYSBlbiBSIGUgaW50ZXJhY3R1YXIgY29uIGxvcyBkYXRvcyBlbiB0b2RhcyBsYXMgZm9ybWFzIHF1ZSBSIG5vcyBwZXJtaXRlLg0KDQpgYGB7cn0NCihNYXRyaW1vbmlvcykNCmBgYA0KDQpMYSB0YWJsYSBub3MgbXVlc3RyYSBlbCBudW1lcm8gZGUgcGVyc29uYXMgcXVlIHNlIGNhc2Fyb24gZW4gTel4aWNvIGVuIDE5OTUgcG9yIGVkYWQgeSBzZXhvLg0KDQpTZSBwdWVkZW4gYfFhZGlyIGNvbWFuZG9zIGFkaWNpb25hbGVzIHBhcmEgZGVmaW5pciBlbCDhcmVhIGEgaW1wb3J0YXIgZGUgbGEgaG9qYSBkZSBj4WxjdWxvLiBFbiBkb25kZSBsb3MgYXJndW1lbnRvcyBkZSBsb3MgY29tYW5kb3MsIHB1ZWRlbiBzZXIgbG9zIHNpZ3VpZW50ZXM6DQoNCmBgYHtyfQ0KRmlsZTogQXJjaGl2byBhIGxlZXJzZSANCg0Kc2hlZXROYW1lOiBOb21icmUgZGUgbGEgaG9qYSBlbiBlbCBhcmNoaXZvIA0KDQpzaGVldEluZGV4OiBO+m1lcm8gZGUgbGEgaG9qYSBlbiBlbCBhcmNoaXZvDQoNCnJvd0luZGV4OiBWZWN0b3IgbnVt6XJpY28gcXVlIGluZGljYSBsYXMgZmlsYXMgcXVlIGRlc2VhIGV4dHJhZXIuIFNpIE5VTEwsIHRvZGFzIGxhcyBmaWxhcyBlbmNvbnRyYWRhcyBzZSBleHRyYWVy4W4sIGEgbWVub3MgcXVlIHNlIGVzcGVjaWZpcXVlIHN0YXJ0Um93IG8gZW5kUm93DQoNCmNvbEluZGV4OiBWZWN0b3IgbnVt6XJpY28gcXVlIGluZGljYSBsYXMgY29sdW1uYXMgcXVlIGRlc2VhIGV4dHJhZXIuIFNpIE5VTEwsIHNlIGV4dHJhZXLhbiB0b2RhcyBsYXMgY29sdW1uYXMgZW5jb250cmFkYXMNCg0KYXMuZGF0YS5mcmFtZTogVmFsb3IgbPNnaWNvIHF1ZSBpbmRpY2Egc2kgZWwgcmVzdWx0YWRvIGRlYmUgc2VyIGNvYWNjaW9uYWRvIGVuIHVuIGFyY2hpdm8gZGF0YS5mcmFtZS4gU2kgRkFMU0UsIGVsIHJlc3VsdGFkbyBlcyB1bmEgbGlzdGEgY29uIHVuIGVsZW1lbnRvIHBhcmEgY2FkYSBjb2x1bW5hLg0KDQpIZWFkZXI6IFZhbG9yIGzzZ2ljbyBxdWUgaW5kaWNhIHNpIGxhIHByaW1lcmEgZmlsYSBjb3JyZXNwb25kaWVudGUgYWwgcHJpbWVyIGVsZW1lbnRvIGRlbCB2ZWN0b3Igcm93SW5kZXggY29udGllbmUgbG9zIG5vbWJyZXMgZGUgbGFzIHZhcmlhYmxlcy4NCg0KQ29sQ2xhc3NlczogUGFyYSByZWFkLnhsc3ggdW4gdmVjdG9yIGRlIGNhcmFjdGVyZXMgcXVlIHJlcHJlc2VudGEgbGEgY2xhc2UgZGUgY2FkYSBjb2x1bW5hLiBTaSBlbCB2ZWN0b3IgZGUgY2FyYWN0ZXJlcyBlcyBub21icmFkbywgbG9zIHZhbG9yZXMgbm8gZXNwZWNpZmljYWRvcyBzZSB0b21hbiBjb21vIE5BLg0KDQpLZWVwRm9ybXVsYXM6IFZhbG9yIGzzZ2ljbyBxdWUgaW5kaWNhIHNpIGxhcyBm83JtdWxhcyBkZSBFeGNlbCBkZWJlbiBtb3N0cmFyc2UgY29tbyB0ZXh0byBlbiBSIHkgbm8gZXZhbHVhZGFzIGFudGVzIGRlIGludHJvZHVjaXJsYXMuDQoNCkVuY29kaW5nOiBDb2RpZmljYWNp824gcGFyYSBsYXMgY2FkZW5hcyBkZSBlbnRyYWRhLg0KDQpTdGFydFJvdzogTvptZXJvIHF1ZSBlc3BlY2lmaWNhIGVsIO1uZGljZSBkZSBsYSBmaWxhIGluaWNpYWwuIFBhcmEgcmVhZC54bHN4IGVzdGUgYXJndW1lbnRvIHPzbG8gZXN04SBhY3Rpdm8gc2kgcm93SW5kZXggZXMgTlVMTC4NCg0KRW5kUm93OiBO+m1lcm8gcXVlIGVzcGVjaWZpY2EgZWwg7W5kaWNlIGRlIGxhIPpsdGltYSBmaWxhIGEgaW1wb3J0YXIuIFNpIGVzIE5VTEwsIGxlYSB0b2RhcyBsYXMgZmlsYXMgZGUgbGEgaG9qYS4gUGFyYSByZWFkLnhsc3ggZXN0ZSBhcmd1bWVudG8gc/NsbyBlc3ThIGFjdGl2byBzaSByb3dJbmRleCBlcyBOVUxMLg0KDQpgYGANCg0KDQojI0VkaXRhciBhcmNoaXZvcyBlbiBFeGNlbA0KDQpBbCBpZ3VhbCBxdWUgcGFyYSBleHRyYWVyIGxhIGluZm9ybWFjafNuIHRlbmVtb3MgcXVlIHRvbWFybGEgZGVzZGUgTWljcm9zb2Z0IEV4Y2VsLCBhbCBjb21wYXJ0aXJsYSBzZSB2dWVsdmUgaW1wb3J0YXJudGUgZWwgcG9kZXIgaGFjZXJsbyBlbiBlc3RlIGZvcm1hdG8gZGUgYXJjaGl2by4gUGFyYSBlbGxvIHhsc3ggdGllbmUgbGEgZnVuY2nzbiBkZSBleHBvcnRhciBpbmZvcm1hY2nzbiBjb24gZWwgc2lndWllbnRlIGNvbWFuZG8uDQoNCmBgYHtyfQ0Kd3JpdGUueGxzeCh4LCBmaWxlLCBzaGVldE5hbWU9IlNoZWV0MSIsDQpjb2wubmFtZXM9VFJVRSwgcm93Lm5hbWVzPVRSVUUsIGFwcGVuZD1GQUxTRSkNCndyaXRlLnhsc3gyKHgsIGZpbGUsIHNoZWV0TmFtZT0iU2hlZXQxIiwNCmNvbC5uYW1lcz1UUlVFLCByb3cubmFtZXM9VFJVRSwgYXBwZW5kPUZBTFNFKQ0KYGBgDQoNCkVuIGRvbmRlIGxvcyBhcmd1bWVudG9zIGRhZG9zIGVuIGxvcyBjb21hbmRvcywgc29uIGxvcyBzaWd1aWVudGVzOg0KDQpYIChNYXJjbyBkZSBkYXRvcyBxdWUgc2UgZXNjcmliaXLhIGVuIGVsIGxpYnJvKQ0KDQpGaWxlIChSdXRhIGFsIGFyY2hpdm8gZGUgc2FsaWRhKQ0KDQpTaGVldE5hbWUgKENhZGVuYSBkZSBjYXJhY3RlcmVzIGEgdXRpbGl6YXIgcGFyYSBlbCBub21icmUgZGUgbGEgaG9qYS4pDQoNCkNvbC5uYW1lcywgcm93Lm5hbWVzIChWYWxvciBs82dpY28gcXVlIGVzcGVjaWZpY2Egc2kgbG9zIG5vbWJyZXMgZGUgY29sdW1uYXMgLyBub21icmVzIGRlIGZpbGFzIGRlIHggZGViZW4gZXNjcmliaXJzZSBlbiBlbCBhcmNoaXZvKQ0KDQpBcHBlbmQgKFZhbG9yIGzzZ2ljbyBxdWUgaW5kaWNhIHNpIHNlIGRlYmUgYfFhZGlyIHggYSB1biBhcmNoaXZvIGV4aXN0ZW50ZSkNCg0KQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLg0KDQpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4NCg0KIyNEYXIgZm9ybWF0byBhIENlbGRhcw0KDQpgYGB7cn0NClMzIG1ldGhvZCBmb3IgY2xhc3MgR0NlbGxTdHlsZUcgY3MxICsgb2JqZWN0DQpgYGANCg0KRWplbXBsbzoNCmBgYHtyfQ0KY3MgPC0gQ2VsbFN0eWxlKHdiKSArDQpGb250KHdiLCBoZWlnaHRJblBvaW50cz0yMCwgaXNCb2xkPVRSVUUsIGlzSXRhbGljPVRSVUUsIG5hbWU9IkNvdXJpZXIgTmV3IiwgY29sb3I9Im9yYW5nZSIpICsNCkZpbGwoYmFja2dyb3VuZENvbG9yPSJsYXZlbmRlciIsIGZvcmVncm91bmRDb2xvcj0ibGF2ZW5kZXIiLCBwYXR0ZXJuPSJTT0xJRF9GT1JFR1JPVU5EIikgKw0KQWxpZ25tZW50KGg9IkFMSUdOX1JJR0hUIikNCmBgYA0KKipCb3JkZXMqKg0KYGBge3J9DQphZGREYXRhRnJhbWUoeCwgc2hlZXQsIGNvbC5uYW1lcz1UUlVFLCByb3cubmFtZXM9VFJVRSwgc3RhcnRSb3c9MSwgc3RhcnRDb2x1bW49MSwgY29sU3R5bGU9TlVMTCwgY29sbmFtZXNTdHlsZT1OVUxMLCByb3duYW1lc1N0eWxlPU5VTEwsIHNob3dOQT1GQUxTRSwgY2hhcmFjdGVyTkE9IiIsIGJ5cm93PUZBTFNFKQ0KYGBgDQoNCiMjUHJpbmNpcGFsZXMgYXJndW1lbnRvcw0KDQpgYGB7cn0NCkNlbGxSYW5nZSAgIENhZGVuYSBxdWUgZXNwZWNpZmljYSBlbCByYW5nbyBkZSBjZWxkYXMuIA0KDQpDb2xJbmRleCAgICBWZWN0b3IgbnVt6XJpY28gcXVlIGVzcGVjaWZpY2EgbGFzIGNvbHVtbmFzIHF1ZSBkZXNlYSB1dGlsaXphciBlbiBlbCB0YW1h8W8gYXV0b23hdGljby4NCg0KQ29sU3BsaXQgICAgVmFsb3IgbnVt6XJpY28gcGFyYSBsYSBjb2x1bW5hIGEgZGl2aWRpci4NCg0KQ29sV2lkdGggICAgICAgIFZhbG9yIG51belyaWNvIHBhcmEgZXNwZWNpZmljYXIgZWwgYW5jaG8gZGUgbGEgY29sdW1uYS4gTGFzIHVuaWRhZGVzIGVzdOFuIGVuIDEgLyAyNTZ0aHMgZGUgdW4gYW5jaG8gZGUgY2Fy4WN0ZXIuDQoNCkRlbm9taW5hZG9yIFZhbG9yIG51belyaWNvIHF1ZSByZXByZXNlbnRhIGVsIGRlbm9taWFkb3IgZGUgbGEgcmVsYWNp824gZGUgem9vbS4NCg0KRW5kQ29sdW1uICAgVmFsb3IgbnVt6XJpY28gcGFyYSBsYSBjb2x1bW5hIGZpbmFsLg0KDQpFbmRSb3cgICAgICBWYWxvciBudW3pcmljbyBwYXJhIGxhIGZpbGEgZmluYWwuDQoNCkluZCAgICAgVmFsb3IgbnVt6XJpY28gcXVlIGluZGljYSBsYSByZWdp824gZnVzaW9uYWRhIHF1ZSBkZXNlYSBlbGltaW5hci4NCg0KTnVtZXJhdG9yICAgICAgIFZhbG9yIG51belyaWNvIHF1ZSByZXByZXNlbnRhIGVsIG51bWVyYWRvciBkZSBsYSByZWxhY2nzbiBkZSB6b29tLg0KDQpQb3NpdGlvbiAgICBDYXJhY3Tpci4gTG9zIHZhbG9yZXMgduFsaWRvcyBzb24gIlBBTkVfTE9XRVJfTEVGVCIsICJQQU5FX0xPV0VSX1JJR0hUIiwgIlBBTkVfVVBQRVJfTEVGVCIsICJQQU5FX1VQUEVSX1JJR0hUIi4NCg0KUm93U3BsaXQgICAgVmFsb3IgbnVt6XJpY28gcGFyYSBsYSBmaWxhIHBhcmEgZGl2aWRpci4NCg0KU2hlZXQgICBPYmpldG8gZGUgaG9qYSBkZSBj4WxjdWxvLg0KDQpTaGVldEluZGV4ICBWYWxvciBudW3pcmljbyBwYXJhIGVsIO1uZGljZSBkZSBob2phIGRlIGPhbGN1bG8uIA0KDQpTdGFydENvbHVtbiBWYWxvciBudW3pcmljbyBwYXJhIGxhIGNvbHVtbmEgZGUgaW5pY2lvLiANCg0KU3RhcnRSb3cgICAgVmFsb3IgbnVt6XJpY28gcGFyYSBsYSBmaWxhIGRlIGluaWNpby4NCg0KWFNwbGl0UG9zICAgVmFsb3IgbnVt6XJpY28gcGFyYSBsYSBwb3NpY2nzbiBob3Jpem9udGFsIGRlIHNwbGl0IGVuIDEvMjAgZGUgdW4gcHVudG8uIA0KDQpZU3BsaXRQb3MgICBWYWxvciBudW3pcmljbyBwYXJhIGxhIHBvc2ljafNuIHZlcnRpY2FsIGRlIHNwbGl0IGVuIDEvMjAgZGUgdW4gcHVudG8uIA0KDQpXYiAgICAgIE9iamV0byBkZSBsaWJyby4NCmBgYA0KDQojIyNDb25jbHVzaW9uDQoNCkxhIGZ1bmNpb25hYmlsaWRhZCBxdWUgbWUgYWdyYWRvIGZ1ZSBsYSBkZSBwb2RlciBpbXBvcnRhciBkYXRvcyBkaXJlY3RhbWVudGUgZGVzZGUgRXhjZWwgc2luIHRlbmVyIHF1ZSBlc3RhciBtYW5pcHVsYW5kbyBhcmNoaXZvcyB5IGNyZWFuZG8gZGF0YXNldHMgZW4gZm9ybWEgbWFudWFsLg0KDQpFbiBsbyByZWZlcmVudGUgYSBsYSBleHBvcnRhY2nzbiB5IGVkaWNp824gZGUgYXJjaGl2b3MgcGFyYSBjb21wYXJ0aXIgaW5mb3JtYWNp824gZW4gZXhjZWwgc2UgdnVlbHZlIGJhc3RhbnRlIGNvbXBsaWNhZG8sIG1lIHBhcmVjZSB1bmEgbWVqb3Igb3BjafNuIGhhY2VybG8gZGlyZWN0YW1lbnRlIGRlc2RlIFIgZW4gTWFya2Rvd24geSBjb21wYXJ0aXJsbyBlbiBodG1sIG8gYmllbiBQREYuDQoNCkZ1ZW50ZXM6DQoNCg0KDQpbUnN0dWRpb10gKGh0dHBzOi8vcnN0dWRpby1wdWJzLXN0YXRpYy5zMy5hbWF6b25hd3MuY29tLzI1MzI5Nl9hMjA2MDhlZGVmYTM0NjgzODU1NTU4NTUxNTU0YWE4Zi5odG1sKQ0KDQpbRWRpY2nzbiBodG1sXSAoaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDMvcm1hcmtkb3duLXNwYW5pc2gucGRmKQ0KDQpbVHV0b3JpYWxlc10gKGh0dHBzOi8vd3d3LnR1dG9yaWFsc3BvaW50LmNvbS9yL3JfZXhjZWxfZmlsZXMuaHRtKQ0KDQpbQWRyaWFuIEEuIERyYWd1bGVzY3VdIChodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMveGxzeC94bHN4LnBkZikNCg==