2015年11月6日金曜日

Asp.net+MVC4でVIEWとContoroller間のajax通信方法

Asp.net+MVC4でVIEWとContoroller間のajax通信方法


【環境】
.NET VB (Microsoft Visual Studio 2010(sp1) .NET Framework 4.5.2)
MVC4

非同期通信を行う

View
@Using Ajax.BeginForm("TestFunc", "TestClass", New AjaxOptions With {.OnSuccess = "viewjs"})
   @<div>
      <input type="submit" value="送信" id="btnSendClick" />
      <input type="text" id="code" />
      <input type="text" id="name" />
   </div>
End Using

<script type="text/javascript">
function viewjs(obj) {
   //通信結果を画面項目に設定
   $("#name").text(obj.name);
}
</script>

 .OnSuccess = "viewjs"
 Contorollerとの通信結果後動作するJavaScript関数を定義

Contoroller
Public Class TestClassController

  <HttpPost()> _
  Public Function TestFunc(ByVal collection As FormCollection) As ActionResult
    Dim model As New TestModel
    If Not Request.IsAjaxRequest() Then
      Return New EmptyResult()
    End If

    //画面入力したcodeでnameを取得するサービスクラス
    model = _Service.TestForAjax(Me.Session, collection("code"))
    Return Json(model)
  End Function
End Class

Model
Public Class TestModel
  Public Property name As String

  Public Sub New()
    name = String.Empty
  End Sub
End Class

2015年8月17日月曜日

Visual Studio2010でExcelの大量のデータの操作(Excelから取得編)

Visual Studio2010でExcelの大量のデータの操作(Excelから取得編)

前回はデータをExcelに表示(設定)する方法を掲載しましたが、今回は逆のExcelから取得です。

セルから1つずつ転送する方法は、転送するデータが少量の場合は問題ありませんが、大量のデータをExcelブックから転送する場合は、この方法はお勧めできません。
大量のデータの操作にはオートメーションを使用してデータの配列にワークシートの特定のセル範囲を転送します。

【環境】
.NET VB (Microsoft Visual Studio 2010(sp1) .NET Framework 4.5.2)
Microsoft Excel 2010

【検証結果】
項目数(Col)40程度のRowを約10,000件操作した場合、
セルを1つずつ転送する方法では処理時間に約3.5分要しました。
データの配列をワークシートに転送する方法では、30秒で終了しました。
(データをDBに登録する処理も含めています。)


セルから1つずつ転送する方法
Dim celval1 As String
Dim celval2 As String
For i As Integer = 2 To ews.UsedRange.Rows.Count + 1
    If Not CType(ews.Cells(i, 0), _
        Global.Microsoft.Office.Interop.Excel.Range).Value2.ToString().Equals( _
        String.Empty) Then

        '1列目の項目を取出し
        celval1 = CType(ews.Cells(i, 0), _
            Global.Microsoft.Office.Interop.Excel.Range).Value2.ToString()
        '2列目の項目を取出し
        celval2 = CType(ews.Cells(i, 1), _
            Global.Microsoft.Office.Interop.Excel.Range).Value2.ToString()
    End If
Next

オートメーションを使用してワークシートからデータの配列に転送する方法
Dim celval1 As String
Dim celval2 As String
'Excelシートの値データ配列に転送
Dim DataArray(,) As Object = _
    CType(ews.Range("A2").Resize( _
        ews.UsedRange.Rows.Count, _
        ews.UsedRange.Columns.Count).Value2, Object(,))

For i As Integer = 1 To ews.UsedRange.Rows.Count
    If Not DataArray(i, 0).ToString().Equals(String.Empty) Then
        '1列目の項目を取出し
        celval1 =  DataArray(i, 0).ToString().Equals(String.Empty)
        '2列目の項目を取出し
        celval2 =  DataArray(i, 1).ToString().Equals(String.Empty)
    End If
Next

【参考】 https://support.microsoft.com/ja-jp/kb/306022

2015年8月3日月曜日

Visual Studio2010でExcelの大量のデータの操作(Excelに表示編)

Visual Studio2010でExcelの大量のデータの操作(Excelに表示編)

セルを1つずつ転送する方法は、転送するデータが少量の場合は問題ありませんが、大量のデータをExcelブックに転送する場合は、この方法はお勧めできません。
大量のデータの操作にはオートメーションを使用してデータの配列をワークシートの特定のセル範囲に転送します。

【環境】
.NET VB (Microsoft Visual Studio 2010(sp1) .NET Framework 4.5.2)
Microsoft Excel 2010

【検証結果】
項目数(Col)40程度のRowを約10,000件操作した場合、
セルを1つずつ転送する方法では処理時間に約10分要しました。
データの配列をワークシートに転送する方法では、数秒で終了しました。

セルを1つずつ転送する方法
Dim dt As DataTable = 【データテーブル取得】
'Excel WorkSheet
Dim ews As Excel.Worksheet = CType(ExcelWorkbook.ActiveSheet, Global.Microsoft.Office.Interop.Excel.Worksheet)
Dim er As Excel.Range

For i As Integer = 0 To dt.Rows.Count - 1
    For j As Integer = 0 To dt.Columns.Count - 1
        er = CType(ews.Cells(i + 2, j + 1), Global.Microsoft.Office.Interop.Excel.Range)
        '書式を設定
        Select Case dt.Columns(j).DataType.Name
            Case "Decimal"
                'er.NumberFormatLocal = "#,##0"
                er.NumberFormatLocal = "G/標準"
            Case "String"
                er.NumberFormatLocal = "@"
            Case Else
                er.NumberFormatLocal = "G/標準"
        End Select
        '値を設定
        er.Value2 = dt.Rows.Item(i).Item(j).ToString()

    Next
    '更新フラグを初期化
    er = CType(ews.Cells(i + 2, CInt(COL.UpdFlg)), Global.Microsoft.Office.Interop.Excel.Range)
    er.NumberFormatLocal = "@"
    er.Value2 = String.Empty
Next

オートメーションを使用してデータの配列をワークシートに転送する方法
Dim dt As DataTable = 【データテーブル取得】
'Excel WorkSheet
Dim ews As Excel.Worksheet = CType(ExcelWorkbook.ActiveSheet, Global.Microsoft.Office.Interop.Excel.Worksheet)
Dim er As Excel.Range
Dim DataArray(dt.Rows.Count - 1, dt.Columns.Count - 1) As Object

For i As Integer = 0 To dt.Rows.Count - 1
    For j As Integer = 0 To dt.Columns.Count - 1
        DataArray(i, j) = dt.Rows.Item(i).Item(j).ToString()
    Next
Next

'属性設定(列単位)
For j As Integer = 0 To dt.Columns.Count - 1
    er = ews.Range(ews.Cells(2, j + 1), ews.Cells(dt.Rows.Count + 1, j + 1))
    Select Case dt.Columns(j).DataType.Name
        Case "Decimal"
            'er.NumberFormatLocal = "#,##0"
            er.NumberFormatLocal = "G/標準"
        Case "String"
            er.NumberFormatLocal = "@"
        Case Else
            er.NumberFormatLocal = "G/標準"
    End Select
Next

'ワークシートの全セルにデータを転送
ews.Range("A2").Resize(dt.Rows.Count, dt.Columns.Count).Value = DataArray

【参考】 https://support.microsoft.com/ja-jp/kb/306022

2015年7月15日水曜日

SQLServerの型と.NET型のマッピング

SQLServerの型と.NET型のマッピング


内容サイズ.NETの型
bit1、0、または NULL の値をとる整数型1Boolean
decimal- 10^38 +1 ~ 10^38 - 1 5~17Decimal
numeric- 10^38 +1 ~ 10^38 - 1 (decimal のシノニム)5~17Decimal
bigint-2^63 (-9,223,372,036,854,775,808) ~ 2^63-1 (9,223,372,036,854,775,807)8Int64
int-2^31 (-2,147,483,648) ~ 2^31-1 (2,147,483,647)4Int32
smallint-2^15 (-32,768) ~ 2^15-1 (32,767)2Int16
tinyint0 ~ 2551Byte
money-922,337,203,685,477.5808 ~ 922,337,203,685,477.58078Decimal
smallmoney- 214,748.3648 ~ 214,748.36474Decimal
float- 1.79E+308 ~ -2.23E-308、0、および 2.23E-308 ~ 1.79E+3084 or 8Decimal
real- 3.40E+38 ~ -1.18E-38、0、および 1.18E-38 ~ 3.40E+384Decimal
Date0001-01-01 ~ 9999-12-313DateTime
datetime20001-01-01 ~ 9999-12-31 00:00:00 ~ 23:59:59.99999996~8DateTime
datetime1753 年 1 月 1 日~ 9999 年 12 月 31 日 00:00:00 ~ 23:59:59.9978DateTime
datetimeoffset0001-01-01 ~ 9999-12-31 00:00:00 ~ 23:59:59.99999998~10DateTimeOffset
smalldatetime1900-01-01 ~ 2079-06-06 00:00:00 ~ 23:59:594DateTime
Time00:00:00.0000000 ~ 23:59:59.99999993~5TimeSpan
char固定長の文字列データ最大長8000String
text可変長の非 Unicode データ (最大長が2^31-1文字)最大長2GBString
varcharUnicode ではない可変長の文字列データ最大長8000String
nchar固定長の Unicode 文字列データ最大長8000String
ntext文字列の最大長が 2^30 - 1 (1,073,741,823) の可変長の Unicode データ最大長2GBString
nvarchar可変長の Unicode 文字列データ最大長8000String
binary長さ n バイトの固定長のバイナリ データ最大長8004Byte[]
varbinary可変長 binary データ最大長8004Byte[]
image0 ~ 2^31-1 (2,147,483,647) バイトの可変長のバイナリ データ最大長2GBByte[]

2015年7月10日金曜日

Visual Studio2010でExcel AddIn開発

Visual Studio2010でExcelのAddInを開発

【環境】
.NET VB (Microsoft Visual Studio 2010(sp1) .NET Framework 4)
Microsoft Excel 2010

【対応】
Visual Studio2010側

1.ファイル>新規作成>プロジェクト>テンプレート>Visual Basic>Office>2010>Excel 2010 アドインを選択


2.SampleExcelAddIn1を作成
 ThisAddIn_Startup()、ThisAddIn_Shutdown()が自動生成される。
 今回は自動生成された関数を使用せずApplication_WorkbookBeforeSave 関数をApplication.WorkbookBeforeSaveにHandlesし新たに作成


Public Class ThisAddIn

    Private Sub ThisAddIn_Startup() Handles Me.Startup

    End Sub

    Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown

    End Sub

    'Excel保存時
    Private Sub Application_WorkbookBeforeSave(ByVal Wb As Microsoft.Office.Interop.Excel.Workbook, ByVal SaveAsUI As Boolean, ByRef Cancel As Boolean) Handles Application.WorkbookBeforeSave
        Dim activeWorksheet As Excel.Worksheet = Application.ActiveSheet

        If activeWorksheet IsNot Nothing Then
            Dim nameCell As Excel.Range = activeWorksheet.Range("B2")
            nameCell.Value2 = "Hello ExcelAddIn"
        End If
    End Sub End Class

3.デバック実行すると以下のようにExcelが起動されB2セルにセットした文字列が表示される。




4.Excelに配置したボタンからAddInを呼び出すようにする。
 「2.」コードを修正


Public Class ThisAddIn

    Private Sub ThisAddIn_Startup() Handles Me.Startup

    End Sub

    Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown

    End Sub

    'Excel保存時
    Private Sub Application_WorkbookBeforeSave(ByVal Wb As Microsoft.Office.Interop.Excel.Workbook, ByVal SaveAsUI As Boolean, ByRef Cancel As Boolean) Handles Application.WorkbookBeforeSave
        Dim activeWorksheet As Excel.Worksheet = Application.ActiveSheet

        If activeWorksheet IsNot Nothing Then
            Dim nameCell As Excel.Range = activeWorksheet.Range("B2")
            nameCell.Value2 = "Hello ExcelAddIn"
        End If
    End Sub End Class

    Private utilities As AddInUtilities
    Protected Overrides Function RequestComAddInAutomationService() As Object
        If utilities Is Nothing Then
            utilities = New AddInUtilities()
        End If
        Return utilities

    End Function

5.他のソリューション(ExcelVBA等)に公開するメンバーを宣言するインターフェイスを定義します。 このインターフェイスをアドイン プロジェクトで定義できます。

 SampleExcelAddIn1プロジェクトにAddInUtilities.vbを追加


Imports System.Runtime.InteropServices
Imports System.Windows.Forms

<ComVisible(True)> _
Public Interface IAddInUtilities
    Sub ImportData()
End Interface

<ComVisible(True)> _
<ClassInterface(ClassInterfaceType.None)> _
Public Class AddInUtilities
    Implements IAddInUtilities

    ' This method tries to write a string to cell A1 in the active worksheet.
    Public Sub ImportData() Implements IAddInUtilities.ImportData
        Dim activeWorksheet As Excel.Worksheet = Globals.ThisAddIn.Application.ActiveSheet
        If activeWorksheet IsNot Nothing Then
            Dim range1 As Excel.Range = activeWorksheet.Range("C3")
            range1.Value2 = "Hello ExcelAddIn ボタン1アクション"
            MessageBox.Show("ボタン1アクションでC3セルに値を設定")
        End If
    End Sub
End Class


6.Excelにマクロを作成
  Excel側
 SampleExcelAddIn1.xlsmを新規作成してボタンを配置



 ボタンのイベントのマクロを作成


Sub ボタン1_Click()
    'すでに"追加シート"シートがあるか確認
    If Worksheets.Count = 1 Then
        Set wkWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count))
        wkWorkSheet.Name = "追加シート"
    Else
        Dim blShoyomst As Boolean
        blShoyomst = False
        For i = 1 To Worksheets.Count
            Set wkWorkSheet = Worksheets(i)
            If wkWorkSheet.Name = "追加シート" Then
                blShoyomst = True
                wkWorkSheet.Select
                Exit For
            End If
        Next
        'あらたに"追加シート"を挿入
        If Not blShoyomst Then
            Set wkWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count))
            wkWorkSheet.Name = "追加シート"
        End If
    End If

    Dim addIn As COMAddIn
    Dim automationObject As Object
    Set addIn = Application.COMAddIns("SampleExcelAddIn1")  '← Visual Studioのアドイン
    Set automationObject = addIn.Object
    automationObject.ImportData         '← 5.で作成したインターフェース
End Sub

7.Visual Studio2010側のSampleExcelAddIn1ソリューションをビルド
 作成したAddInを設定
 開発>COMアドイン



8.ボタンクリックしてAddIn実行



2015年7月6日月曜日

SPREAD Enterキーでセルのタブ移動

SPREAD for Windows Forms5.0でEnterキーでセルのタブ移動する設定。

【事象】
汎用機等の利用者が旧システムと同様操作ができるようにEnterキーでセルのタブ移動をするようしたいと言う要求があります。
その設定(コード)を書きとめる。

【環境】
.NET VB (Microsoft Visual Studio 2010(sp1) .NET Framework 4)
SPREAD for Windows Forms Version : 5.0.2025.2008(SP3)(グレープシティ株式会社)

【対応】
以下のコードで対応

Enterキーで移動
Private Sub frmTail_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
    Dim im As New FarPoint.Win.Spread.InputMap
    'Enterキーで移動を追加
    '非編集セルでの[Enter]キーを「次行へ移動」とします
    im = vaSpread1.GetInputMap(FarPoint.Win.Spread.InputMapMode.WhenFocused)
    im.Put(New FarPoint.Win.Spread.Keystroke(Keys.Enter, Keys.None),        FarPoint.Win.Spread.SpreadActions.MoveToNextColumnWrap)

    '編集中セルでの[Enter]キーを「次行へ移動」とします
    im = vaSpread1.GetInputMap(FarPoint.Win.Spread.InputMapMode.WhenAncestorOfFocused)
    im.Put(New FarPoint.Win.Spread.Keystroke(Keys.Enter, Keys.None),     FarPoint.Win.Spread.SpreadActions.MoveToNextColumnWrap)
End Sub



コンボボックEnterキー押下でTab移動する
'コンボボックスオブジェクト
Private WithEvents _Combo As New FarPoint.Win.FpCombo()
    'Enterキーが押されたフラグ
    Dim bEnterKey As Boolean

Private Sub vaSpread1_EditModeOn(sender As System.Object, e As System.EventArgs) Handles vaSpread1.EditModeOn
    'セル型がコンボボックス型の場合は、EditingControlをComboにマッピングする 
    Dim iRow As Integer = vaSpread1.ActiveSheet.ActiveRowIndex 
    Dim iCol As Integer = vaSpread1.ActiveSheet.ActiveColumnIndex

    If TypeOf (vaSpread1.ActiveSheet.GetCellType(iRow, iCol)) Is FarPoint.Win.Spread.CellType.ComboBoxCellType Then
        _Combo = CType(vaSpread1.EditingControl, FarPoint.Win.FpCombo)
    End If
End Sub

Private Sub _Combo_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles _Combo.KeyDown
    ' Enterキーが押された場合にフラグを立てる
    bEnterKey = (e.KeyCode = Keys.Enter)
End Sub

Private Sub _Combo_DropDown(ByVal sender As Object, ByVal e As FarPoint.Win.DropDownEventArgs) Handles _Combo.DropDown
    ' フラグが立っている場合は、DropDown処理をキャンセルする
    If Not bEnterKey Then
        Return
    End If
    e.Cancel = bEnterKey
    bEnterKey = False

    ' アクティブセルを右隣に移動
    SendKeys.Send("{Tab}")
End Sub

'一覧コンボボックで空白選択だできない対応
Private Sub vaSpread1_ComboSelChange(sender As System.Object, e As FarPoint.Win.Spread.EditorNotifyEventArgs) Handles vaSpread1.ComboSelChange
    Dim cb As FarPoint.Win.FpCombo = CType(e.EditingControl, FarPoint.Win.FpCombo)
    If cb.SelectedItem.Equals(String.Empty) Then
        cb.Clear()
    End If
End Sub

ExcelCreator 8.0でテンプレ-トの関数が有効にならない

【環境】
.NET VB (Microsoft Visual Studio 2010(sp1) .NET Framework 4)
ExcelCreator 8.0 for .NET(アドバンスソフトウェア株式会社)

【事象】
ExcelCreator 8.0でテンプレ-トで設定したExcelの関数が有効にならない。
ExcelCreatorで生成したExcelブックを一度、開いて対象のセルを選択しEnterキーを押下すると反映される。
Excelブックを開いた時に関数を有効にしたい。

【対応】
以下のコードで対応
ExcelCreator.FullCalcOnLoad = True

HELPの説明
ブックオープン時の再計算の有効モードを設定します。

詳細情報がインターネット上で検索できななかった。