0

SQL Server 2005 データベースを使用して、VB.net 4.0 で記述された従来の Windows デスクトップ アプリケーションを使用しています。アプリケーションは、データベースに保存されている Word テンプレートに基づいてレポートを生成します。レポートのテキストに変更があった場合に備えて、新しい Word レポート テンプレート (.docx) をデータベースにロードできる管理セクションがあります。管理フォームでは、新しいファイルを追加したり、既存のファイルを削除または更新したりできます。新しいファイルを追加するとき、それが格納されているデータベース ルックアップ テーブル内のファイルの主キーとして使用されるコード (テキスト) を要求します。また、データベースからファイルを選択して開くこともできるので、見た。

次の動作は一貫して再現できます。 新しいコード (主キー) を使用して新しい .docx ファイルを追加できます。そのファイルは正常に開くことができます。既存のファイルが新しい .docx で更新された場合、開こうとすると、Word で「ファイルを開くときにエラーが発生しました」というエラー メッセージが表示されて失敗します。そのファイルのレコードが削除され、同じファイルが新しいコード (PK) で追加された場合、正常に開くことができます。削除されたファイルと同じコード (PK) を使用して同じファイル (または任意の .docx ファイル) が追加された場合、DB への書き込みは問題ないように見えますが、ファイルを開こうとすると失敗し、上記と同じエラー メッセージが表示されます。 .

開くことができない .docx ファイルは、正常に開くことができる場合よりも 1 バイト長くなります。Word で開くことができない .docx ファイルは、アーカイブとして (たとえば 7zip で) 開くことができ、ファイルの内容は同じように見えます。

既存のファイルを上書きしたり、削除されたファイルのコード (PK) を他のファイル タイプ (.doc を含む) で再利用したりすることは正常に機能します。.docx ファイルのみが問題を引き起こしています。レポートの生成は、Word 文書の内容を OpenXML コードで操作することによって行われるため、.docx ファイルが必要となるため、これは残念です。

ファイルをデータベースに挿入するコードは次のとおりです。

Private Sub btnInsert_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles     btnInsert.Click
    Dim sName As String = InputBox("What is the name of this Resource")
    If (sName.Length > 0) Then
        Dim ofd As New OpenFileDialog
        With ofd
            .CheckFileExists = True
            .ShowReadOnly = False
            .Filter = "All Files|*.*"
            If (.ShowDialog = DialogResult.OK) Then
                Dim fs As FileStream = New FileStream(.FileName, FileMode.Open, FileAccess.Read)
                Dim docByte As Byte() = New Byte(fs.Length - 1) {}
                fs.Read(docByte, 0, Convert.ToInt32(fs.Length))
                fs.Close()

                Dim FileType As String = Path.GetExtension(.FileName).ToLower

                Dim conn As New SqlConnection(strConnString)
                Dim cmd As New SqlCommand(sqlInsert, conn)
                cmd.Parameters.AddWithValue("@ID", sName)
                cmd.Parameters.AddWithValue("@Bytes", docByte)
                cmd.Parameters.AddWithValue("@Types", FileType)

                conn.Open()
                cmd.ExecuteNonQuery()
                conn.Close()

                MsgBox("Saved to DB")
                Dim li As ListViewItem = lvwResource.Items.Add(sName)
                li.SubItems.Add(FileType)

                docByte = Nothing
                fs.Dispose()
            End If
        End With
    End If
End Sub

そして、取得するコード:

Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click

    Dim sName As String = lvwResource.SelectedItems(0).Text
    Dim sType As String = lvwResource.SelectedItems(0).SubItems(1).Text
    Dim fileName As String = String.Format("{0}{1}{2}", Path.GetTempPath, sName, sType)

    Dim conn As New SqlConnection(strConnString)
    Dim cmd As New SqlCommand(sqlSelect, conn)
    cmd.Parameters.AddWithValue("@ID", sName)

    Dim da As New SqlDataAdapter(cmd)

    Dim dt As New DataTable
    da.Fill(dt)

    Dim docByte() As Byte = dt.Rows(0)(1)
    Dim fs As New FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)
    fs.Write(docByte, 0, Convert.ToInt32(docByte.Length))
    fs.Dispose()

    Try
        System.Diagnostics.Process.Start(fileName)
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Question, "Unknown Resource Type")
    End Try
End Sub

詳細: ワークステーションは Windows XP SP3 with Microsoft Office 2003 SP3、サーバーは Server 2003 Standard edition SP2、db は SQL Server 2005 SP2 です。それは大規模な組織であり、私は彼らの時代遅れのソフトウェアに対して何の影響力も持っていません.

4

1 に答える 1

0

OK、解決策が見つかりました。MSDN フォーラムの Franklin Chan には、時間と忍耐を持って私を助けてくれたことに感謝します。

エラーは、私がここに投稿したことのない更新コードにありました (私の悪い!)。

更新するファイルと既存のレコードを読み取ると、次のコードがありました。

Dim fs As FileStream = New FileStream(.FileName, FileMode.Open)
Dim img As Byte() = New Byte(fs.Length) {}
fs.Read(img, 0, fs.Length)
fs.Close()

おかしなことに、私は挿入サブで正しい方法でそれを行っていました。正しい構文は次のとおりです。

Dim fs As FileStream = New FileStream(.FileName, FileMode.Open, FileAccess.Read)
Dim img As Byte() = New Byte(fs.Length - 1) {}
fs.Read(img, 0, Convert.ToInt32(fs.Length))
fs.Close()

欠落していたもう 1 つの重要な手順は、データベースから抽出して開く前に一時ファイルをクリアすることでした。そのため、以下を追加します。

If System.IO.File.Exists(fileName) = True Then
    System.IO.File.Delete(fileName)
End If

btnOpen() コードに。

于 2013-11-21T01:48:45.350 に答える