quinta-feira, 4 de agosto de 2011

Trabalhando com Microsoft.Office.Interop.MSProject (Parte 1 – Demonstração do problema)

Olá!

Neste post, gostaria de compartilhar algo que sofri muito para fazer. Pesquisei muito sobre e não achei exemplos claros. Com isto, tive que desenvolver meu objetivo através do método de tentativa e erro! Irei então separar este post em duas partes. Na primeira parte, irei apenas demonstrar meu problema. Na segunda parte, mostro como foi resolvido.

A situação era a seguinte:
Lá na empresa temos uma aplicação que faz o gerenciamento de projetos, através de atividades. Estes projetos possuem N atividades filhas, assim como estas filhas possuem também N outras atividades filhas.. Ou seja, uma árvore, uma hierarquia de atividades.
Com a usabilidade, os clientes tiveram a necessidade de importar os projetos que gerenciavam através do Microsoft Office Project para nossa aplicação. Então, um amigo chamado José Roberto, desenvolveu um PLUGIN para o MS Project utilizando uma biblioteca chamada Microsoft.Office.Interop.MSProject . A função deste PLUGIN era, através da biblioteca e utilizando o C#, pegar cada atividade do MS Project e criar um registro desta atividade em nossa aplicação, respeitando a hierarquia.

Até então estava ok, pois o PLUGIN funcionava conforme foi desenvolvido e os clientes utilizavam normalmente.

Porém, surgiu uma nova necessidade. E com isto Eis o problema:
Os clientes solicitaram um MERGE entre o MS Project e nossa aplicação, onde o sistema teria de garantir que o MERGE iria atualizar somente as alterações mais recentes.
Lembra aquelas ferramentas que fazem merge de código fonte? WinMerge, Beyond Compare? Pronto! É algo semelhante! Porém, estas ferramentas trabalham com linhas e meu objetivo era um MERGE hierárquico..

Imaginemos que o seguinte projeto foi criado no MS Project:


Porém, este projeto vai sendo alterado na ferramenta que foi desenvolvida. E aqui surge a necessidade: quando o projeto e suas atividades são alterados, deseja-se comparar os dois projetos no sentido de verificar e atualizar os dois lados (MS Project e aplicação) sempre com a alteração mais recente.
Exemplo:




Na figura acima, temos na cor vermelha as alterações que foram feitas nas informações de uma atividade. Como exemplo, no MS Project temos a atividade Tarefa 1, e no Sistema o nome da atividade foi alterado para Tarefa primeira. O objetivo da implementação é identificar neste conflito qual a alteração maios recente e atualizar conforme seja. Se a alteração para a segunda atividade (Tarefa 1 no MS Project) mais recente foi no MS Project, então a atividade Tarefa 1 vai mudar o nome para Tarefa Primeira. Caso a alteração mais recente seja no Sistema, então o nome desta mesma atividade no sistema vai mudar para Tarefa 1. Daí a regra vai para todas as colunas.

O leitor deve ter percebido a complexidade do problema, pois se a estrutura (digo estrutura no sentido de a quantidade de atividade ser a mesma em ambos os lados, com os mesmos níveis da árvore) for a mesma em ambos os lados, fica muito fácil pois é só varrer a lista de maneira hierárquica (utilizando recursividade) e comparar linha a linha. Porém, e se eu apagar uma certa atividade no sistema? E se no MS Project eu resolver adicionar mais uma atividade em um certo ponto do projeto?

Resumindo, o merge tem que atender os seguintes requisitos:

- Comparar alteração de campo da atividade mais recente para modificar o campo mais antigo
- Verificar se a data da exclusão de uma atividade no MS Project é mais atual que a data de modificação desta mesma atividade no Sistema. Se sim, então exclui também no sistema. Se não, então restaura a atividade no MS Project.
- Verificar se a data da exclusão de uma atividade no Sistema é mais atual que a data de modificação desta mesma atividade no MS Project. Se sim, então exclui também no MS Project. Se não, então restaura a atividade no Sistema.
- Quando criar uma atividade no MS Project, criar também no Sistema, obedecendo a hierarquia.
- Quando criar uma atividade no Sistema, criar também no MS Project, obedecendo a hierarquia.
- Quando mover uma atividade no MS Project para uma outra atividade, fazer também a mudança no Sistema.
- Quando mover uma atividade no Sistema para uma outra atividade, fazer também a mudança no MS Project.
- Para cada requisito acima, mostrar na tela uma tela onde mostra cada situação. Exemplo: Se foi excluído do MS Project e é mais recente, então perguntar: Atividade “X” excluída do MS Project. Deseja excluir no sistema? Sim, Sim para Todos, Não e Não para Todos. Se usuário clicar em Sim para Todos, o sistema irá colocar sim para todas as situações acima. No caso da comparação de alteração de campo, mostra tela com todos os campos e informações, e mostrar qual foi a alteração.

A princípio parecem fácil os requisitos. Mas devemos lembrar que estamos trabalhando com hierarquia. Ou seja, no exemplo de uma atividade excluída pode ser que esta atividade seja Pai de N outras atividades. Na figura acima, imagine se faço a exclusão da atividade Tarefa 1. Quando faço a exclusão desta atividade, tudo que está abaixo também será excluído. Ou seja, as atividades Subtarefa 1 e Subtarefa 2 também serão excluídas.

Como será o merge desta situação?:


Meu objetivo neste post, é demonstrar não só a solução deste problema, mas também como utilizar a biblioteca Microsoft.Office.Interop.MSProject e suas classes para nos apoiar na solução. Nesta primeira parte fiz a explicação do problema. Ainda esta semana estarei colocando a solução. Qualquer dúvida ou sugestão não deixe de colocar comentários.

Até a próxima!

Sócrates de Halley

Nenhum comentário:

Postar um comentário