2011-08-16 49 views
1

我有一个类系:caculate基于树形结构的行和cols生成excel文件

class Department{ 
    string des; 
    string name; 
    string id; 
    List<Department> subDeps; 
} 

正如代码所示,一个部门可以有若干个子所在部门。

现在,我已经从数据库中读取了信息,并且得到了根部门对象。

然后我想生成一个Excel工作表这样的方式:

enter image description here

事实上,根“部门”对象是一个树形结构。

当我尝试将项目写入Excel表格时,我必须决定项目的行和列,但是我无法做到。

而且有人可以帮我一个忙吗?

回答

2

看看这样说:

0 00 000 | (0,0) (0,1) (0,2) 
    001 |    (1,2) 
1 10 100 | (2,0) (2,1) (2,2) 
    101 |    (3,2) 
    11  |  (4,1) 

我用同样的语法可以命名节点(左侧)和相应的位置“(行,列)”到网格(右侧) 。这里有两个顶级部门,0和1. 您可以用“(x,y)”坐标为每个树/顶级部门的深度首次访问标记节点。每当你从父亲到孩子下降,你必须增加1列号。 每次你访问一个新的兄弟姐妹时,你的行索引必须指向一个新的空行(在这个例子中,10的兄弟姐妹是11,但是你(3,1)不能放入,因为第3行已被101部门占用)。

我会按照这些指南编写算法。使用作为递归深度优先访问的参数传递的两个变量以及要访问的当前节点/部门来跟踪当前(x,y)。确保函数根据需要编辑excel表示,但返回使用的最大行索引(以便您可以在访问新的同级时使用它来知道下一行是哪一行 - 如前例所示)。 每次您进行递归调用时,都必须用coords(x,y + 1)调用它,因为它是一个新列。以类似的方式,当你访问一个新的兄弟姐妹时,你用(coords prev_call_retn + 1,y)调用它,因为它是一个新行(其中coords_prev_call_retn是前一个兄弟上次递归调用的值)。 辅助函数将调用根节点上的递归函数,并将其用作基础坐标(0,0)或任何您喜欢的起点。

#include <iostream> 
#include <list> 
#include <string> 

using namespace std; 

class Dept { 
public: 
    string id; 
    list<Dept*> *subDepts; 

    Dept(string id) { 
     this->id = id; 
     this->subDepts = new list<Dept*>(); 
    } 

    Dept *addChild(Dept *d) { 
     this->subDepts->push_back(d); 
     return d; 
    } 

    Dept *addChild(string id) { 
     Dept *d = new Dept(id); 
     return this->addChild(d); 
    } 

}; 

void visit(Dept *d, int row, int col) { 
    cout << "Dept " << d->id << ": (" << row << ", " << col << ")\n"; 
} 

int label(Dept *d, int row, int col) { 
    if (d == 0) return row; 
    visit(d, row, col); 
    list<Dept*> *lst = d->subDepts; 
    for (list<Dept*>::iterator it = lst->begin() ; it != lst->end(); it++) 
    { 
     row = label(*it, row, col+1) + 1; 
    } 
    if (lst->size() > 0) row--; 
    return row; 
} 

int label(Dept *d) { 
    label(d, 0, 0); 
} 

在这个C++代码,标签()是你感兴趣的函数。

参数ROW和COL都应该是部门* d的正确的坐标,这样我们就可以立即访问该节点。

循环递归调用每个孩子(如果有的话)的label()。请注意,我使用变量行来跟踪最后一次使用的行+1。

最后,我们必须返回函数上次使用的行,但要小心减去一个,如果d-> subDepts不是空的。这是因为在上一次迭代中增加了1行的for循环。

下面是主要的一个例子:

int main(int argc, char **argv) { 
    Dept *d0 = new Dept("0"); 
    Dept *d00 = d0->addChild("00"); 
    Dept *d01 = d0->addChild("01"); 
    Dept *d000 = d00->addChild("000"); 
    Dept *d001 = d00->addChild("001"); 
    Dept *d002 = d00->addChild("002"); 
    Dept *d010 = d01->addChild("010"); 
    Dept *d02 = d0->addChild("02"); 
    label(d0); 
    return 0; 
} 

而这里的结果:

bash-4.2$ g++ dept.cpp && ./a.out 
Dept 0: (0, 0) 
Dept 00: (0, 1) 
Dept 000: (0, 2) 
Dept 001: (1, 2) 
Dept 002: (2, 2) 
Dept 01: (3, 1) 
Dept 010: (3, 2) 
Dept 02: (4, 1) 

我希望这有助于。

+0

感谢您的良好回答,我尝试编写代码,但我无法做到,我不擅长算法。你有空时可以抽出一些时间吗? – hguser

+0

不客气。在这里,我通过添加一个有效的C++示例来编辑我的答案。 –

+0

,谢谢。它的工作原理,但是我不知道是否有任何可以计算每个单元格的行跨度和列跨度?在你的例子中,'Dep0'将取一列和两行,'Dep11'取两列和一行。 – hguser

0

如果您想按照您的示例进行布局,使用colspans来对齐单元格,那么在没有先发现或事先知道(硬编码)的情况下,我看不出有任何方法可以这样做,最大深度的树 - 你需要这个来确定用于部门的总列数。一些表格属性的

假设(将有助于理解下面的代码):

  • 只有最右边的单元跨越多个列,其他所有的列表ColWidth 1个
  • 最右边的细胞从未跨越多行,总有colHeight 1
  • 存在着一些函数来计算最大宽度,或者可替换地最大列索引,对于该表的“部门”的一部分(设置在代码中的变量或blockWidthmaxY

伪布局表:

displayDeptTree(Department root) { 
    startX, startY: beginning coord of the root dept 
    blockWidth: total no. of columns (tree depth + 1, or hardcoded to value > possible depth) 
    maxY = startY + blockWidth - 1 // global var? 

    addDeptIntoCell(root, startX, startY) 
} 

// returns height of the cell 
int addDeptIntoCell(Department d, x, y) { 
    colHeight = 1 
    if (d->subDeps is empty) { 
     colWidth = maxY - y 
     addDepartment(d, x, y, colHeight, colWidth) // colHeight = 1 always 
    } else { 
     currY = y 
     for (Dept child : d->subDeps) { 
      childHeight = addDeptIntoCell(child, x + 1, currY); // increment x pos for children 
      currY += childHeight 
     } 
     colHeight = currY - y 
     addDepartment(d, x, colHeight, 1) 
    } 
    return colHeight 
} 


addDepartment(Department d, x, y, height, width) { 
    // Actually adds the department info into table, parameters should be self-explanatory, implementation not shown 
} 

这可能是一个错误等有过,而且我用D-> subDeps Java中的不是C++指针的尊重,但你应该得到的一般想法:)