DOBON.NETプログラミング道掲示板
(現在 過去ログ2 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33411 / inTopicNo.1)  チェックボックスでチェックしたものだけをツリービューの階層通りにコピーしたい
  
□投稿者/ たえこ 一般人(1回)-(2016/07/03(Sun) 16:30:10)
  • アイコン環境/言語:[win7、VB.NET2010] 
    分類:[.NET] 

    ツリービューでチェックしたフォルダだけをコピーしたい

    環境WIN7、VB.NET2010を利用しています

    ツリービューに、Cドライブのフォルダの一覧を表示させております
    TEXTBOX1があり、バックアップ先を表示させています
    ツリービューにチェックボックスがあり、チェックしたフォルダだけを
    textbox1に表示させているパス名にコピーするプログラムを作成しております

    チェックボックスにチェックしたものだけを、ツリービューの階層通りに
    コピーしたく思います

    下記コードになります
    Imports System.IO

    Public Class Form1

    Private Sub TreeView1_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck

    If e.Node.Parent Is Nothing Then
    Exit Sub
    End If

    '全ての子ノードのチェックボックスを連動
    SetCheck(e.Node.Checked, e.Node.Nodes)

    End Sub

    Private Sub SetCheck(Check As Boolean, nodes As TreeNodeCollection)
    For Each n As TreeNode In nodes
    n.Checked = Check
    SetCheck(Check, n.Nodes)
    Next
    End Sub

    Private Sub SetChildren(baseNode As TreeNode)
    For Each subDir As String In Directory.GetDirectories(baseNode.FullPath)
    Dim n As TreeNode = baseNode.Nodes.Add(Path.GetFileName(subDir))
    n.Checked = baseNode.Checked
    Try
    If Directory.GetDirectories(subDir).Any() Then
    n.Nodes.Add("NUL")
    End If
    Catch ex As Exception
    End Try
    Next

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
    TreeView1.CheckBoxes = True
    Dim rootNode As TreeNode = TreeView1.Nodes.Add("C:", "C:\")
    SetChildren(rootNode)
    rootNode.Expand()
    End Sub

    Private Sub TreeView1_BeforeExpand(sender As Object, e As TreeViewCancelEventArgs) Handles TreeView1.BeforeExpand

    If e.Node.Nodes(0).Text = "NUL" Then
    e.Node.Nodes.RemoveAt(0)
    SetChildren(e.Node)
    End If

    End Sub

    Private Sub Button0_Click(sender As System.Object, e As System.EventArgs) Handles Button0.Click
    'FolderBrowserDialogクラスのインスタンスを作成
    Dim fbd As New FolderBrowserDialog
    'fbdに表示するテキスト指定
    fbd.Description = "バックアップフォルダを選択もしくは作成を行なって下さい"
    'ダイアログ表示
    If fbd.ShowDialog(Me) = DialogResult.OK Then
    End If
    'TEXTBOX1に表示
    TextBox1.Text = fbd.SelectedPath
    End Sub

    Private Sub GetFolders(node As TreeNode)
    '子ノードをクリア
    node.Nodes.Clear()
    '設定されたフォルダの直下のサブフォルダを検索
    For Each folder As String In Directory.GetDirectories(node.FullPath)
    '子ノードを追加
    node.Nodes.Add(Path.GetFileName(folder))

    If node.Checked Then
    node.Nodes(node.Nodes.Count - 1).Checked = True
    End If

    Try
    'サブフォルダが存在していたらダミーのノードを追加
    If Directory.GetDirectories(folder).Count > 0 Then
    node.Nodes(node.Nodes.Count - 1).Nodes.Add("dmy")
    End If

    Catch ex As Exception
    End Try
    Next
    End Sub

    Private Sub GetCopyFolders(node As TreeNode, folders As List(Of String))

    '最下層のノードを対象にチェックボックスがオンのノードのフルパスをリストに追加
    For Each n As TreeNode In node.Nodes
    GetCopyFolders(n, folders)
    Next

    'ノードのチェックボックスがオンならリストに追加
    If node.Nodes.Count = 0 Then Exit Sub
    If node.Checked Then
    folders.Add(node.FullPath)
    End If

    End Sub

    Private Sub Button6_Click(sender As System.Object, e As System.EventArgs) Handles Button6.Click

    Dim TFolders As New List(Of String)

    'バックアップ対象フォルダのリストを取得
    For Each node As TreeNode In TreeView1.Nodes(0).Nodes
    GetCopyFolders(node, TFolders)
    Next

    'バックアップ対象未選択

    If TFolders.Count = 0 Then
    MessageBox.Show("チェック", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    Exit Sub
    End If

    'バックアップ対象選択済
    If MessageBox.Show("コピーを行ないますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = Windows.Forms.DialogResult.Yes Then
    'Exit Sub

    '「はい」ならバックアップを実行…

    For Each srcFolder As String In TFolders

    Me.Cursor = Cursors.WaitCursor
    Try
    Dim bkFolder As String = System.IO.Path.Combine(TextBox1.Text, Path.GetFileName(srcFolder))
    My.Computer.FileSystem.CopyDirectory(srcFolder, bkFolder, FileIO.UIOption.AllDialogs)

    Catch ex As Exception
    MessageBox.Show(srcFolder & vbCrLf & "コピー失敗", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    Me.Cursor = Cursors.Default
    Exit Sub
    End Try
    Next

    Me.Cursor = Cursors.Default
    MessageBox.Show(Me, "コピー終了", "通知")

    '「いいえ」ならメッセージ表示…
    ElseIf Windows.Forms.DialogResult.No Then
    MessageBox.Show("コピー不可", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    End If

    End Sub

    Private Sub Button9_Click(sender As System.Object, e As System.EventArgs) Handles Button9.Click
    'TREEVIEWチェックを外す
    For Each node As TreeNode In TreeView1.Nodes(0).Nodes
    node.Checked = False
    Next node

    End Sub

    End Class

    下記フォルダ構成の場合、コピーを行うことが出来ません

    @C:\フォルダ0\フォルダ1
    AC:\フォルダ4
    BC:\フォルダ5\フォルダ6
     C:\フォルダ5\フォルダ7
    C:\フォルダ5\フォルダ8\フォルダ10
    C:\フォルダ5\フォルダ9\フォルダ11

    @でフォルダ0のみを選択しコピーを行なうと、
    フォルダ0とフォルダ1がコピーされる為、フォルダ0のみをコピーしたい

    @でフォルダ1のみを選択しコピーを行なうと、チェックと表示される為、
    フォルダ1のみをコピーしたい
    Aでフォルダ4を選択してコピーを行なうと、チェックと表示される為、
    フォルダ4をコピーしたい

    Bでフォルダ5以下を選択し、ツリービューを展開させてからコピーを行なうと、
    フォルダ5がコピーされ、その階層にフォルダ8とフォルダ9がコピーされる為
    フォルダ5以下を選択し、ツリービューを展開させても展開させなくても、
    フォルダ5をコピー(フォルダ5の階層にはフォルダ5のみ)し、フォルダ5の中にフォルダ6とフォルダ7、フォルダ8とフォルダ9をコピーして、
    フォルダ8の中にフォルダ10、フォルダ9の中にフォルダ11をコピーしたい

    Bでフォルダ6、フォルダ7、フォルダ8、フォルダ9を選択してコピーを行なうと、フォルダ6とフォルダ7がコピーされず、フォルダ8とフォルダ9がコピーされ、フォルダ8の中にフォルダ10、フォルダ9の中にフォルダ11がコピーされる為
    フォルダ6とフォルダ7をコピーして、フォルダ8の中にフォルダ10、フォルダ9の中にフォルダ11をコピーしたい

    @でフォルダ0以下を選択し、Aでフォルダ4を選択してコピーを行なうと、@のフォルダ0以下のみがコピーされる為、フォルダ0以下とフォルダ4をコピーしたい

    ツリービューを展開させてもさせなくてもチェックボックスで
    チェックしたものだけを、ツリービューの階層通りにコピーしたく思います

    長文乱文を読んで頂きまして、本当にありがとうございました

    ツリービューを展開させてもさせなくてもチェックしたフォルダだけを
    コピーする方法を教えていただけませんでしょうか

引用返信 削除キー/
■33412 / inTopicNo.2)  Re[1]: チェックボックスでチェックしたものだけをツリービューの階層通りにコピーしたい
□投稿者/ 魔界の仮面弁士 大御所(1036回)-(2016/07/04(Mon) 07:21:03)
  • アイコンNo33411に返信(たえこさんの記事)
    > ツリービューでチェックしたフォルダだけをコピーしたい
    コードの一部に迸るデジャヴ感。
    http://bbs.wankuma.com/index.cgi?mode=al2&namber=79840


    > 下記コードになります
    これは幾つかのサンプルコードを切り張りしたものなのでしょうか?

    たとえば、サブフォルダの存在を確認する部分で
    > If Directory.GetDirectories(subDir).Any() Then
    > If Directory.GetDirectories(folder).Count > 0 Then
    のような表記揺れが見られ、コードに一貫性がありません。


    > '「いいえ」ならメッセージ表示…
    > ElseIf Windows.Forms.DialogResult.No Then

    判定方法が間違っています。

    こういう場合は、メッセージボックスの結果を変数に受け取り、
    その値と比較するようにしましょう。


    Dim 変数 = MessageBox.Show("コピーを行ないますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)
    If 変数 = System.Windows.Forms.DialogResult.Yes Then
     '……
    ElseIf 変数 = Windows.Forms.DialogResult.No Then
     '……
    End If


    あるいは、今回は YesNoCancel の 3 値判定ではなく
    YesNo の 2 値選択なので、単に Else 句を使うという手もあります。

    If MessageBox.Show(…) = System.Windows.Forms.DialogResult.Yes Then
     '…
    Else
     '…
    End If


    > 下記フォルダ構成の場合、コピーを行うことが出来ません
    2008年8月以降、「フォルダ」ではなく「フォルダー」表記に統一されています。
    http://www.atmarkit.co.jp/news/200807/25/microsoft.html


    > @でフォルダ0のみを選択しコピーを行なうと、
    > フォルダ0とフォルダ1がコピーされる為、フォルダ0のみをコピーしたい
    NUL マーカーのあるノードが選択されていた場合は
    その下位のフォルダーもコピーするように実装しましょう。

    そして NUL マーカーが除去されているノードが選択されていた場合は、
    自フォルダーの直下のファイルのみをコピーしたのち、
    子ノードのチェック状態を見ながら、再帰的にコピーするように
    実装すれば良いかと思います。
引用返信 削除キー/
■33413 / inTopicNo.3)  Re[2]: チェックボックスでチェックしたものだけをツリービューの階層通りにコピーしたい
□投稿者/ たえこ 一般人(2回)-(2016/07/04(Mon) 08:20:48)
  • アイコン魔界の仮面弁士様

    回答ありがとうございます。
    サンプルコードを切り貼りしたものです。

    C# と VB.NET の質問掲示板を見ていましたら、
    コードがあったので切り貼りしました。
    コードに一貫性がないのも、切り貼りしている為です。

    バイク様と私は同一ではありません。
    類似質問で不信感を抱かせてしまって、申し訳ございません。

    大変恐縮ではありますが
    可能なら、コードでご教授頂けませんでしょうか?



引用返信 削除キー/
■33414 / inTopicNo.4)  Re[3]: チェックボックスでチェックしたものだけをツリービューの階層通りにコピーしたい
□投稿者/ たえこ 一般人(3回)-(2016/07/04(Mon) 21:13:04)
  • アイコン魔界の仮面弁士様

    回答ありがとうございます

    NUL マーカーのあるノードが選択されていた場合は
    その下位のフォルダーもコピーするように実装する。

    NUL マーカーが除去されているノードが選択されていた場合は、
    自フォルダーの直下のファイルのみをコピーしたのち、
    子ノードのチェック状態を見ながら、
    再帰的にコピーするように実装する。

    →フォルダーのコピーをする方法が出来てないため
    目的を達する事ができていないと思いますが、
    参考になるHPやサンプルコードなど、ありませんでしょうか?

引用返信 削除キー/
■33415 / inTopicNo.5)  Re[4]: チェックボックスでチェックしたものだけをツリービューの階層通りにコピーしたい
□投稿者/ 魔界の仮面弁士 大御所(1037回)-(2016/07/05(Tue) 17:29:14)
  • アイコンNo33413に返信(たえこさんの記事)
    > 類似質問で不信感を抱かせてしまって、申し訳ございません。
    こちらこそ済みません。不信感も不審感も抱いてはおりませんが、
    最近自分が書いたばかりのコードが出現してむず痒かったので、
    ちょっと反応してしまいました。
    (私の間違えた部分もそのまま転記されていたので…)



    No33414に返信(たえこさんの記事)
    > 参考になるHPやサンプルコードなど、ありませんでしょうか?
    今ごらんになっているサイト(DOBON.NET プログラミング道)の
    [.NET Tips]-[ファイル、フォルダ編]などは如何でしょうか。
    http://dobon.net/vb/dotnet/file/index.html


    > →フォルダーのコピーをする方法が出来てないため

    My.Computer.FileSystem.CopyDirectory では除外条件は指定できません。

    また、権限不足のファイルやフォルダー、あるいはリパースポイントなどがあると
    処理が例外で中断されてしまう可能性があります。

    そのためコピー処理はフォルダー単位ではなく、ファイル単位で
    行うようにし、サブフォルダーの作成なども自前で行うことになります。


    > NUL マーカー
    コピー云々はさておき、対象フォルダーを列挙するサンプルを作ってみました。


    本来であれば Yield Return ステートメントを使って列挙するべき所ですが、
    Yield は VB2012 以降でないと使えないため、ここではイベント通知で代用しています。


    Public Event Notice(ByVal sourceDir As String)

    Private Sub SampleButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles SampleButton.Click
      ListBox1.Items.Clear()
      EnumCheckedPath(TreeView1.Nodes(0))
    End Sub

    Private Sub Form1_Notice(ByVal sourceDir As String) Handles Me.Notice
      '実際には ListBox に表示するのではなく、
      'このフォルダーにあるファイル群をコピーするための処理を記述します
      ListBox1.Items.Add(sourceDir)
    End Sub

    Public Sub EnumCheckedPath(ByVal node As TreeNode)
      If node Is Nothing Then
        Throw New ArgumentNullException("node")
      End If

      'チェックがついていれば、コピー対象として通知します
      If node.Checked AndAlso node.Text <> "NUL" Then
        RaiseEvent Notice(node.FullPath)

        'チェック付きノードの下に NUL マーカーがあった場合は
        '下位のフォルダーもチェックが付いているものとみなして、
        'サブディレクトリすべてを列挙します
        If Not node.FirstNode Is Nothing AndAlso node.FirstNode.Text = "NUL" Then
          Try
            For Each subDir In Directory.GetDirectories(node.FullPath, "*", SearchOption.AllDirectories)
              RaiseEvent Notice(subDir)
            Next
          Catch
          End Try
        End If
      End If

      For Each subNode As TreeNode In node.Nodes
        EnumCheckedPath(subNode)
      Next
    End Sub


    なお上記では、SearchOption.AllDirectories 指定での列挙を行っていますが
    これは手抜き実装であり、本来はお奨めしません。

    AllDirectories を使った場合、アクセス権の無いフォルダに指し当たった時に
    列挙が失敗してしまいますし、対象アイテムが多くなると非常に遅くなるためです。

    この問題を回避するには、Directory(または DirectoryInfo) の
    GetDirectories メソッドを呼ぶ際に、AllDirectories モードではなく
    TopDirectoryOnly モードを指定して、再帰的に処理するようにしてみてください。
引用返信 削除キー/
■33422 / inTopicNo.6)  Re[5]: チェックボックスでチェックしたものだけをツリービューの階層通りにコピーしたい
□投稿者/ たえこ 一般人(4回)-(2016/07/11(Mon) 12:17:05)
  • アイコン魔界の仮面弁士様

    回答ありがとうございます

    My.Computer.FileSystem.CopyDirectory では
    除外条件は指定出来ませんとの事ですが、
    Treeviewでフォルダのコピーをする際、指定して行うことは
    出来ないのでしょうか?


引用返信 削除キー/
■33423 / inTopicNo.7)  Re[6]: チェックボックスでチェックしたものだけをツリービューの階層通りにコピーしたい
□投稿者/ 魔界の仮面弁士 大御所(1041回)-(2016/07/11(Mon) 13:25:09)
  • アイコン2016/07/11(Mon) 13:26:42 編集(投稿者)

    No33422に返信(たえこさんの記事)
    > My.Computer.FileSystem.CopyDirectory では
    > 除外条件は指定出来ませんとの事ですが、
    はい。なので、『サブフォルダのファイル「も」コピーする』のではなく、
    『TreeView で指定したフォルダのファイル「だけ」をコピーする』ように
    書き変える必要があります。

    そのための手順については、先に紹介した [.NET Tips] をご覧ください。

    > Treeviewでフォルダのコピーをする際、指定して行うことは
    TreeView で選択されたフォルダーを列挙するコードは既に提示しておりますので、
    そこに上記のコピー処理を自力で組み込んでみてください。
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -