VB.NET - Controle de visitas médicas - II


Este artigo é continuação do  VB.NET - Controle de visitas médicas - I , se você não leu o artigo anterior clique no link e acompanhe a definição das tabelas da base de dados e do dataset tipado.

Nota: Para saber mais sobre datasets tipados veja os artigos:

Nossa aplicação tem por objetivo registrar as visitas a pacientes e gerar uma receita para cada paciente com os dados cadastrados para pacientes , medicamentos e diagnósticos. A aplicação deverá efetuar portanto o cadastro de pacientes , medicamentos e diagnósticos para em seguida registrar as visitas feitas usando os dados cadastrados.

Vamos criar o formulário de menu da aplicação incluindo um novo formulário no projeto com o nome de Menu.vb e definindo a sua propriedade isMdiContainer como True. A seguir inclua um componente no MenuStrip no formulário e crie um menu com as seguintes opções:

Vamos agora incluir um novo formulário com o nome de pacientes.vb. Neste formulário será efetuado o cadastro dos pacientes. Vamos usar o assistente do VB 2005. Abra a janela Data Sources e selecione a tabela pacientes clicando a seguir na seta para baixo. Selecione a opção Details e a seguir arraste e solte a tabela no formulário criado. O assistente irá criar os campos da tabela e todo o menu para navegação e realização das operações CRUD (create, read, update e delete) no formulário. Veja na figura abaixo:

Devemos incluir mais dois formulários: medicamentos.vb e diagnosticos.vb e repetir a operação feita acima usando as tabelas medicamentos e diagnosticos de forma a criar os formulários conforme abaixo:

O formulário de visitas é o mais complexo pois nele devemos ter as informações cadastradas para além de atualizar as tabelas de visitas, pacienteMedicamentos e pacienteDiagnosticos também gerar o receituário para o paciente com gravação do arquivo com nome do paciente e impressão do mesmo.

Abaixo temos o leiaute do formulário contendo os controles relativos aos dados que deverão ser exibidos ou informados.

 Inclua um novo formulário visitas.vb no seu projeto. Menu Project opção Add Windows Form...

Para poder exibir os pacientes cadastrados vamos usar um controle combobox para fazer isto na janela Data Sources selecione a tabela pacientes e selecione a opção Combobox arrastando em seguida a tabela para o formulário visitas.vb.

Serão criados os componentes no formulário:

  1. DiagnosticoDataSet - é a referência do formulário para a fonte de dados DiagnosticoDataSet.xsd
  2. PacientesBindingSource - é a referência ao objeto bindingSource que unifica a vinculação dos dados.
  3. PacientesTableAdapter - é o invólucro para um objeto SqlDataAdapter que preenche o DataTable pacientes do DiagnosticoDataSet
  4. PacientesBindingNavigator - é um ToolStrip customizado. A sua vinculação com o PacientesBindingSource  permite a navegação pelos dados.

Selecione o componente visual PacientesBindingNavigator e o exclua do projeto.

Se você espiar o evento Load do formulário irá ver que o assistente criou a seguinte linha de código:   Me.PacientesTableAdapter.Fill(Me.DiagnosticoDataSet.pacientes)

Esta linha de código irá preencher a combobox com os dados dos pacientes cadastrados que é exatamente o que queremos obter. A combobox é identificada por pacientesComboBox.
 

Vamos repetir o processo acima para criar a combobox que irá exibir os diagnósticos cadastrados: diagnosticosComboBox (usando a tabela diagnosticos) e para a combobox que irá exibir os medicamentos cadastrados: MedicamentosCombobox (usando a tabela medicamentos). Clique na tabela na janela Data Sources selecione a opção ComboBox, arraste a tabela para o formulário e exclua o componente BindingNavigator.

Com isto já podemos selecionar o paciente e o diagnóstico para o paciente, mas aqui temos um problema, pois podemos ter mais de um medicamento indicado para o paciente/diagnóstico em questão. Para resolver isto vamos incluir um controle ListBox(lstbMedicamentos) e um botão de comando para que possamos selecionar um medicamento e clicando no botão de comando incluir o medicamento no ListBox com isto podermos indicar mais de um medicamento para o paciente/diagnóstico.

A solução adotada acima nos remete a um outro problema: devemos atualizar a tabela pacienteMedicamentos com o ID do medicamento mas temos somente o nome do mesmo na ListBox(lstbMedicamentos). Para poder obter o ID de cada medicamento incluído no controle ListBox temos que criar uma classe para obter esta informação. Inclua um módulo de classe no projeto; no menu Project selecione a opção Add Class e informe o nome lbMedicamentos.vb e no módulo inclua o seguinte código:

Nota: A ausência da propriedade ItemData presente no VB5/VB6 deverá ser criada usando a classe. Para saber mais sobre o assunto leia o artigo: VB.NET - Ressuscitando a propriedade ItemData

Public Class lbMedicamentos

    Private sNome As String
    Private iID As Integer

    ' construtor padrão vazio
    Public Sub New()
        sNome = ""
        iID = 0
    End Sub
    Public Sub New(ByVal Nome As String, ByVal ID As Integer)
        sNome = Nome
        iID = ID
    End Sub
    Public Property Nome() As String
        Get
            Return sNome
        End Get
        Set(ByVal sValue As String)
            sNome = sValue
        End Set
    End Property

    'esta propriedade irá obter o ID do item do listbox
    Public Property ItemData() As Int32
        Get
            Return iID
        End Get
        Set(ByVal iValue As Int32)
            iID = iValue
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return sNome
    End Function
End Class

Vamos voltar a falar sobre esta classe quando comentarmos o código da aplicação.

Inclua um controle TextBox (txtNotas) para informar as recomendações do médico ao paciente. Inclua também 3 botões de comando : btnSalvar , btnDescartar e btnSalvaImprime.

Nota: Devemos incluir arrastar e soltar as tabelas pacientesMedicamentos e pacienteDiagnosticos para o formulário para obtermos os componentes Adapter correspondentes.

Ao final desta etapa o formulário deverá exibir além dos controles incluídos os componentes no formulário conforme figura abaixo:

Analisando o código da aplicação

Se você espiar o evento Load do formulário visitas.vb irá notar que o assistente já criou o código para preencher os TableAdapters criados.

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'TODO: This line of code loads data into the 'DiagnosticoDataSet.visitas' table. You can move, or remove it, as needed.
        Me.VisitasTableAdapter.Fill(Me.DiagnosticoDataSet.visitas)
        'TODO: This line of code loads data into the 'DiagnosticoDataSet.pacienteDiagnosticos' table. You can move, or remove it, as needed.
        Me.PacienteDiagnosticosTableAdapter.Fill(Me.DiagnosticoDataSet.pacienteDiagnosticos)
        'TODO: This line of code loads data into the 'DiagnosticoDataSet.pacienteMedicamentos' table. You can move, or remove it, as needed.
        Me.PacienteMedicamentosTableAdapter.Fill(Me.DiagnosticoDataSet.pacienteMedicamentos)
        'TODO: This line of code loads data into the 'DiagnosticoDataSet.medicamentos' table. You can move, or remove it, as needed.
        Me.MedicamentosTableAdapter.Fill(Me.DiagnosticoDataSet.medicamentos)
        'TODO: This line of code loads data into the 'DiagnosticoDataSet.diagnosticos' table. You can move, or remove it, as needed.
        Me.DiagnosticosTableAdapter.Fill(Me.DiagnosticoDataSet.diagnosticos)
        'TODO: This line of code loads data into the 'DiagnosticoDataSet.pacientes' table. You can move, or remove it, as needed.
        Me.PacientesTableAdapter.Fill(Me.DiagnosticoDataSet.pacientes)
   End Sub

O código do formulário principal que contém o menu de opções do sistema é o formulário menu.vb que irá abrir os demais formulários como formulários filhos do formulário MDI é dado a seguir:

Public Class Menu
 

Private Sub PacientesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles          PacientesToolStripMenuItem.Click

   My.Forms.pacientes.MdiParent = Me

   My.Forms.pacientes.Show()

End Sub

 

Private Sub MedicamentosToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MedicamentosToolStripMenuItem.Click

   My.Forms.medicamentos.MdiParent = Me

   My.Forms.medicamentos.Show()

End Sub

 

Private Sub DiagnósticosToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DiagnósticosToolStripMenuItem.Click

   My.Forms.diagnosticos.MdiParent = Me

   My.Forms.diagnosticos.Show()

End Sub

 

Private Sub RegistrarVisitaToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RegistrarVisitaToolStripMenuItem.Click

   My.Forms.visitas.MdiParent = Me

   My.Forms.visitas.Show()

End Sub

 

Private Sub SobreToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SobreToolStripMenuItem.Click

   My.Forms.sobre.MdiParent = Me

   My.Forms.sobre.Show()

End Sub

 

Private Sub SairToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SairToolStripMenuItem.Click

If (MsgBox("Confirma encerramento da aplicação ? ", MsgBoxStyle.YesNo) = MsgBoxResult.Yes) Then

   Me.Close()

End If

End Sub
 

End Class

Vamos criar o código do evento Click do botão - Receitar Medicamento - ele deverá obter o medicamento selecionado no combobox e incluir no ListBox. Inclua o código abaixo no evento Click do botão:

Private Sub btnIncluiMedicamento_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnIncluiMedicamento.Click

'obtem o ID e o nome do medicamento e usando a classe lbMedicamanto inclui no controle ListBox
Dim medicamentoID As Integer = Convert.ToInt32(MedicamentosComboBox.SelectedValue)
Dim medicamentoNome As String = CType
((MedicamentosComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString

lstbMedicamentos.Items.Add(New lbMedicamentos(medicamentoNome, medicamentoID))

End Sub

As duas primeiras linhas de código obtêm o ID e o nome do medicamento a partir do combobox. Agora perceba a última linha de código; nela estamos incluindo o item selecionado na ListBox(lstbMedicamentos) usando a classe lbMedicamentos que foi criada para permitir a recuperação do ID do medicamento da ListBox, simulando a propriedade ItemData.

Vejamos a seguir o código do evento Click do botão - Gravar Registro e gera receituário:

Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click
 

'obtem o ID e o nome do paciente

Dim pacienteID As Integer = Convert.ToInt32(PacientesComboBox.SelectedValue)

pacienteNome = CType((PacientesComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString


'obtem o ID e a descrição do diagnóstico

Dim diagnosticoID As Integer = Convert.ToInt32(DiagnosticosComboBox.SelectedValue)

Dim diagnosticoDescricao As String = CType((DiagnosticosComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString


'define a data/hora como sendo a atual

Dim datainicio As DateTime = DateTime.Now
 

'atualiza as tabelas de visitas e de PacientesDiagnosticos

Me.VisitasTableAdapter.Insert(pacienteID, datainicio, txtNotas.Text)

Me.PacienteDiagnosticosTableAdapter.Insert(pacienteID, diagnosticoID)


Dim
listaMedicamentos As
lbMedicamentos

Dim medicamentos As String = ""


'percorre o ListBox com os medicamentos receitados e inclui na receita

For i As Integer = 0 To Me.lstbMedicamentos.Items.Count - 1

   'selecione o item

   Me.lstbMedicamentos.SetSelected(i, True)

   ' Obtem o item selecionado

   listaMedicamentos = lstbMedicamentos.Items(lstbMedicamentos.SelectedIndex)

   'inclui o item na tabela PacienteMedicamentos

   Dim nIncluido As Integer = PacienteMedicamentosTableAdapter.Insert(pacienteID, listaMedicamentos.ItemData, datainicio)

   medicamentos = medicamentos & (lstbMedicamentos.SelectedItem).ToString & vbCrLf


  
'se ocorreu um erro na inclusão avisa

   If nIncluido <> 1 Then

         MessageBox.Show("Não foi possivel receitar o medicamento", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)

   End If

Next
End
Sub

Este código obtém os dados informados e usando o método Insert do objeto TableAdapter atualiza as tabelas pertinentes. Note que como recuperamos o ID do medicamento usando a propriedade ItemData da classe lbMedicamentos.

Criando o arquivo .doc para mesclar os dados da aplicação

Mas o código não esta completo devemos poder mesclar as informações com o documento Word para gerar a receita para o paciente com seu diagnóstico , medicamento e recomendações.

Vamos criar no Word , eu estou usando o Word 2003, um documento chamado receita.doc contendo as seguintes informações:

Salve o arquivo em um diretório separado, eu usei a pasta d:\teste\. Neste documento as variáveis estão sendo identificadas pelo símbolo @ no início das mesmas pois iremos substituir cada uma delas com informações vindas da aplicação VB.

Agora podemos concluir o código do botão - Gravar Registro e gera receituário:

Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click
 

'obtem o ID e o nome do paciente

Dim pacienteID As Integer = Convert.ToInt32(PacientesComboBox.SelectedValue)

pacienteNome = CType((PacientesComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString


'obtem o ID e a descrição do diagnóstico

Dim diagnosticoID As Integer = Convert.ToInt32(DiagnosticosComboBox.SelectedValue)

Dim diagnosticoDescricao As String = CType((DiagnosticosComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString


'define a data/hora como sendo a atual

Dim datainicio As DateTime = DateTime.Now
 

'atualiza as tabelas de visitas e de PacientesDiagnosticos

Me.VisitasTableAdapter.Insert(pacienteID, datainicio, txtNotas.Text)

Me.PacienteDiagnosticosTableAdapter.Insert(pacienteID, diagnosticoID)


Dim
listaMedicamentos As
lbMedicamentos

Dim medicamentos As String = ""


'percorre o ListBox com os medicamentos receitados e inclui na receita

For i As Integer = 0 To Me.lstbMedicamentos.Items.Count - 1

   'selecione o item

   Me.lstbMedicamentos.SetSelected(i, True)

   ' Obtem o item selecionado

   listaMedicamentos = lstbMedicamentos.Items(lstbMedicamentos.SelectedIndex)

   'inclui o item na tabela PacienteMedicamentos

   Dim nIncluido As Integer = PacienteMedicamentosTableAdapter.Insert(pacienteID, listaMedicamentos.ItemData, datainicio)

   medicamentos = medicamentos & (lstbMedicamentos.SelectedItem).ToString & vbCrLf


  
'se ocorreu um erro na inclusão avisa

   If nIncluido <> 1 Then

         MessageBox.Show("Não foi possivel receitar o medicamento", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)

   End If

Next

'inicia geração da receita com substituição dos valores
Try
'Instancia a Aplicação Word.
objWord = CreateObject(
"Word.Application"
)

'Abre o documento aviso.doc do Microsoft Word.
objWord.Documents.Open(
"d:\teste\receita.doc"
)

'Procura pela palavra "@escola" e substitui pelo conteúdo indicado
SubstituiVariavel(
"@clinica", "JcmSoft - Clinica Geral"
)

SubstituiVariavel("@medico", "Dr. José Carlos Macoratti")

SubstituiVariavel("@data", Today)

SubstituiVariavel("@endereco", "SHS 912 Conjunto C Bloco A Sala 21")

SubstituiVariavel("@cidade", "Brasilia-DF")

SubstituiVariavel("@paciente", pacienteNome)

SubstituiVariavel("@diagnostico", diagnosticoDescricao)

SubstituiVariavel("@medicamentos", medicamentos)

If txtNotas.Text.Length > 0 Then

   SubstituiVariavel("@recomendacao", txtNotas.Text)

End If

SubstituiVariavel("@clinico", "Dr. Jose C. Macoratti")


If MsgBox("Confirma abertura do documento?", MsgBoxStyle.YesNo, "Microsoft Word - Aviso.doc") = MsgBoxResult.Yes Then

  'torna o Word visivel

  objWord.visible = True

  'habilita o botão para fechar o word sem salvar

Else

   fechaWord()

End If

Catch ex As Exception

  MsgBox("Ocorreu um erro durante a geração do receituário", MsgBoxStyle.Critical, "Erro")

  objWord.ActiveDocument.Close(False)

  objWord.Quit()

  objWord = Nothing

  MsgBox(ex.Message)

End Try


End
Sub

Para podermos usar este código temos que efetuar uma referência COM no nosso projeto. Existem outras formam de efetuar uma chamada a uma aplicativo Office a partir do VB.NET. Para referenciar o Word no seu projeto clique com o botão direito do mouse sobre o nome do projeto selecione a opção Add Reference. A seguir clique na guia COM da janela Add Reference e selecione a opção : Microsoft Word 11.0 Object Library (pode haver variações dependendo da sua versão do Word).

A seguir temos o código da rotina SubstituiVariavel que irá mesclar as informações da aplicação VB com o arquivo .doc.

Private Sub SubstituiVariavel(ByVal Achar As String, ByVal Substituir As String)

        'procura a variável e substitui o valor 
        With objWord.Selection.Find
            .Text = Achar.ToString
            .Replacement.Text = Substituir.ToString
            .Forward = True
            .Format = False
            .MatchCase = False
            .MatchWholeWord = False
            .MatchWildcards = False
            .MatchSoundsLike = False
            .MatchAllWordForms = False

            While .Execute = True
                objWord.Selection.Select()
                System.Windows.Forms.Clipboard.SetDataObject(Substituir)
                objWord.Selection.Paste()
            End While
        End With
    End Sub

 

A seguir o código dos demais botões de comando:

Private Sub btnSalvaImprime_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvaImprime.Click
        fechaWord(pacienteNome)
End Sub
Private Sub btnDescartar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDescartar.Click
        Me.Close()
 End Sub

 

A rotina fechaWord irá salvar e imprimir o documento Word usando o nome do paciente com a extensão doc no caminho definido. Perceba que o parâmetro pacienteNome é opcional e por isto tem que ter um valor padrão definido. Se o nome for passado o arquivo é salvo e impresso e somente depois será fechado.

 

Private Sub fechaWord(Optional ByVal pacienteNome As String = "")

        'se o nome do paciente foi usado como parâmetro salva o arquivo e imprime
        If pacienteNome.Length > 0 Then
            objWord.ActiveDocument.SaveAs(FileName:=caminho & pacienteNome & ".doc", LockComments:=False, Password:="", AddToRecentFiles:=True, 
                     WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData:=False, 
                     SaveAsAOCELetter:=False)
            objWord.Application.PrintOut(FileName:="", Copies:=1, Pages:="", ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _
                 False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
                 PrintZoomPaperHeight:=0)
        End If
        'Fecha o documento Word
        objWord.ActiveDocument.Close(False)
        'Fecha o Word
        objWord.Quit()
        objWord = Nothing
    End Sub

 

Inclua no início do código do formulário as seguintes declarações para o objeto Word , para o caminho do arquivo .doc a ser salvo e para o nome do paciente.

Dim objWord As Object
Dim
caminho As String =
"d:\teste\"
Dim pacienteNome As String

Já podemos rodar a aplicação e ver o resultado conforme exibido nas figuras a seguir:

1- O formulário visitas.vb preenchido com os dados já cadastrados:

2-  Ao clicar no botão - Gravar Registro e gerar receituário, as informações são mescladas com o arquivo receita.doc ,  o arquivo é salvo e impresso na impressora padrão.  Abaixo o arquivo .doc exibindo as informações após efetuar a substituição das variáveis.

Como eu já mencionei existem maneiras mais elegantes para usar os aplicativos Office do que apelar para o COM , em futuros artigos estarei abordando estas possibilidades. De qualquer forma, como você acompanhou é bem simples criar o seu aplicativo no VB 2005 e fazer a integração com o Word.

O texto do arquivo receita.doc é meramente ilustrativo e você pode fazer os ajustes necessários as suas necessidades bem como usar o seu talento para aperfeiçoar o projeto expandido-o com novas funcionalidades.

Nota: Se você analisar com cuidado a normalização utilizada irá verificar que alguns ajustes serão necessários dependendo do ajuste que você pretende fazer na aplicação.

O projeto completo esta no Super DVD .NET (com opção de relatórios via printDocument)

Até o próximo artigo  ...


José Carlos Macoratti