Hola AROJAS.
Como dice Ramiro con el árbol visor de tablas es coser y cantar.
Sin embargo, si eres un intrépido puedes probar con el TreeView.
Prueba el siguiente ejemplo:
- La tabla arbolada tiene la siguiente estructura: CUENTAS(ID alfa40(8), NAME alfa256(100), PADRE alfa40(8))
- El campo PADRE contiene el ID de la rama Padre de cada registro. Si isEmpty(PADRE) entonces el registro es un TopLevel
var oArbol = theRoot.dataView().control("CTR_ARBOL")
// Columnas del árbol
var nColID = 0
var nColName = 1
var nColPadre = 2
oArbol.clear()
// El doble click se reserva para editar la Rama
oArbol.expandsOnDoubleClick = false
oArbol.wordWrap = true
oArbol.textElideMode = VTreeWidget.ElideRight
oArbol.indentation = 10
oArbol.animated = true
oArbol.rootIsDecorated = true
oArbol.uniformRowHeights = true
oArbol.alternatingRowColors = true
var cTabla = "MiProyecto_dat/CUENTAS"
// Fuentes para decorar
var oFuenteNegrita = new VFont("courier")
oFuenteNegrita.setPixelSize(12)
oFuenteNegrita.setBold(true)
var oFuenteNormal = new VFont("consolas")
var oFuenteCourier = new VFont("courier")
// Cabeceras
oArbol.headerHidden = false
oArbol.setHeaderLabel("Cuentas contables") // No aparece cuando usamos setHeaderLabels()
oArbol.setHeaderLabels(["Cuenta", "Nombre", "Padre"])
// Cargamos la lista de Cuentas ordenada por el ID para ir rellenando desde arriba hacia abajo
var oLisCuentas = new VRegisterList(theRoot)
oLisCuentas.setTable(cTabla)
oLisCuentas.load("ID",[])
var oItemPadre = null, oItemHija = null, oItemPadreScroll = null
// Recorremos la Lista y vamos insertando las Ramas en su Padre correspondiente
for (var i = 0 ; i < oLisCuentas.size(); ++i) {
var oItem = oLisCuentas.readAt(i)
var cID = oItem.fieldToString("ID") // ID único de cada rama
var cNombre = oItem.fieldToString("NAME") // Nombre de la Rama
var cIdPadre = oItem.fieldToString("PADRE") // ID del Padre de la rama
// Añadimos un Item
if (cIdPadre === "") {
// El Item es TopLevel
var oItemPadre = oArbol.addTopLevelItem()
oItemPadre.setText(nColID, cID)
oItemPadre.setText(nColName, cNombre)
oItemPadre.setText(nColPadre, cIdPadre)
oItemPadre.setFont(nColID, oFuenteNegrita)
oItemPadre.setForegroundColor(nColName,139,0,0,255)
oItemPadre.setBackgroundColor(nColName,240,230,140,255)
// CID_PADRE_SCROLL guarda el ID de la rama TopLevel selecionada al inicio
if (theRoot.varToString("CID_PADRE_SCROLL") == cID) {
oItemPadreScroll = oItemPadre
}
}
else {
// La Opción es hija.
// Comprobamos si la rama padre actual oItemPadre es la correcta, de lo contrario
// tenemos que buscar la Rama padre de forma recursiva
if (oItemPadre && (oItemPadre.text(nColID) != cIdPadre)) {
// No podemos buscar un Item directamente en el árbol TreeWidget por su ID
// Tenemos que buscar el Item Padre de forma recursiva recorriendo las ramas
oItemPadre = buscarPadre_Arbol(cIdPadre, oArbol)
}
// Mostramos solo los Valores asignados si lSoloConValor = true
if (oItemPadre) {
oItemHija = oItemPadre.addChild()
oItemHija.setText(nColID, cID)
oItemHija.setText(nColName, cNombre)
oItemHija.setText(nColPadre, cIdPadre)
oItemHija.setFont(nColID, oFuenteCourier)
oItemHija.setFont(nColName, oFuenteNormal)
oItemHija.setForegroundColor(nColName,105,105,105,255)
oItemHija.setBackgroundColor(nColName,255,248,220,255)
}
}
}
function buscarPadre_Arbol(cIdPadre, oArbol) {
// Recorremos cada rama de los topLevelItem
var oItemPadre = null
for(var t = 0 ; t < oArbol.topLevelItemCount; ++t) {
oItemPadre = buscarPadre_Rama(cIdPadre, oArbol.topLevelItem(t))
if (oItemPadre) break
}
return oItemPadre
}
function buscarPadre_Rama(cIdPadre, oItemRama) {
var oItemPadre = null
// Recorremos las subramas para buscar el ID del padre
for(var x = 0 ; x < oItemRama.childCount(); ++x) {
// Comprobamos la columna del ID
var oItem = oItemRama.child(x)
if (oItem.text(nColID) == cIdPadre) {
// Se ha encontrado el Padre, lo retorna y termina el bucle
return oItem
}
else {
// Buscamos de forma recursiva
oItemPadre = buscarPadre_Rama(cIdPadre, oItem)
}
}
return oItemPadre
}
// Ocultamos la columna con el ID del Padre
oArbol.hideColumn(nColPadre)
// Expandimos las ramas
oArbol.expandToDepth(3)
// Damos ancho fijo a la 1ª columna
oArbol.setColumnWidth(nColID, 150)
// oArbol.resizeColumnToContents(nColID)
// Activamos y mostramos el Item escogido
if (oItemPadreScroll){
oArbol.scrollToItem(oItemPadreScroll, VTreeWidget.PositionAtCenter)
oArbol.setCurrentItem(oItemPadreScroll, 0)
}
Como muchos objetos en Velneo, el Widget TreeView no es una excepción y está bastante incompleto, con algún que otro bug (por ejemplo el menú contextual) que por alguna oscura razón lleva años sin solución.
De todas formas lo que hay funciona bastante bien.
Adjunto imagen con el resultado del ejemplo.
Saludos
Paco Satué