├── .gitignore ├── README.md ├── SAPExtractorDotNET.sln ├── SAPExtractorDotNET ├── My Project │ ├── Application.Designer.vb │ ├── Application.myapp │ ├── AssemblyInfo.vb │ ├── Resources.Designer.vb │ ├── Resources.resx │ ├── Settings.Designer.vb │ └── Settings.settings ├── SAPConnector.vb ├── SAPExtractorDotNET.vbproj ├── SAPFieldItem.vb ├── SAPQueryExtractor.vb ├── SAPTableExtractor.vb └── lib │ └── .keep ├── SAPExtractorDotNETTest ├── My Project │ ├── Application.Designer.vb │ ├── Application.myapp │ ├── AssemblyInfo.vb │ ├── Resources.Designer.vb │ ├── Resources.resx │ ├── Settings.Designer.vb │ └── Settings.settings ├── QueryExtraction.vb ├── ResultWriter.vb ├── SAPExtractorDotNETTest.vbproj ├── TableExtraction.vb └── app.config ├── documents └── SAPExtractorDotNETAPI.shfbproj └── saploader ├── App.config ├── MainModule.vb ├── My Project ├── Application.Designer.vb ├── Application.myapp ├── AssemblyInfo.vb ├── Resources.Designer.vb ├── Resources.resx ├── Settings.Designer.vb └── Settings.settings ├── README.md ├── quickstart └── saploader.zip └── saploader.vbproj /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj/ 2 | [Bb]in/ 3 | *.user 4 | /TestResults 5 | *.vspscc 6 | *.vssscc 7 | deploy 8 | deploy/* 9 | *.suo 10 | *.cache 11 | *.docstates 12 | _ReSharper.* 13 | *.vbproj.user 14 | *[Rr]e[Ss]harper.user 15 | _ReSharper.*/ 16 | packages/ 17 | artifacts/* 18 | msbuild.log 19 | LastBuild.log 20 | *.shfbproj_* 21 | Help/ 22 | *.nupkg 23 | SAPExtractorDotNET/lib/*.dll 24 | app.Debug.config 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SAPExtractorDotNET 2 | ============= 3 | 4 | This is connector for SAP system. 5 | You can extract data from Table or Query. 6 | 7 | [API Documentation](http://icoxfog417.github.io/SAPExtractorDotNET/Index.html) 8 | [Install from Nuget](https://www.nuget.org/packages/SAPExtractorDotNET) 9 | 10 | ## Set up 11 | 1. Clone this repository 12 | 2. Download SAP .NET Connector from [SAP Service Marketplace](https://websmp110.sap-ag.de/connectors). 13 | After download, move below dlls to `SAPExtractorDotNET/lib` folder. 14 | 15 | * libicudecnumber.dll 16 | * rscp4n.dll 17 | * sapnco.dll 18 | * sapnco_utils.dll 19 | 20 | ## How to use 21 | Below is code sample (see test project code). 22 | (repository is builded by x86, if your system is x64 then build it by SAPExtractorDotNET/SAPNco(x64)) 23 | **[You can use it by command line! see saploader's README](https://github.com/icoxfog417/SAPExtractorDotNET/tree/master/saploader)** 24 | 25 | ### Extract from Table 26 | 27 | C# 28 | 29 | ```csharp 30 | SAPConnector connector = new SAPConnector(TestDestination); 31 | 32 | try { 33 | RfcDestination connection = connector.Login; 34 | 35 | SAPTableExtractor tableExtractor = new SAPTableExtractor(TestTable); 36 | DataTable table = tableExtractor.Invoke(connection, { 37 | "BUKRS", 38 | "BUTXT" 39 | }, new SAPFieldItem("SPRAS").IsEqualTo("EN")); 40 | ResultWriter.Write(table); 41 | 42 | } catch (Exception ex) { 43 | Console.WriteLine(ex.Message); 44 | } 45 | ``` 46 | 47 | VB.Net 48 | 49 | ```vbnet 50 | Dim connector As New SAPConnector(TestDestination) 51 | 52 | Try 53 | Dim connection As RfcDestination = connector.Login 54 | 55 | Dim tableExtractor As New SAPTableExtractor(TestTable) 56 | Dim table As DataTable = tableExtractor.Invoke(connection, {"BUKRS", "BUTXT"}, New SAPFieldItem("SPRAS").IsEqualTo("EN")) 57 | ResultWriter.Write(table) 58 | 59 | Catch ex As Exception 60 | Console.WriteLine(ex.Message) 61 | End Try 62 | ``` 63 | 64 | ### Extract from SAP Query 65 | 66 | C# 67 | 68 | ```csharp 69 | SAPConnector connector = new SAPConnector(TestDestination); 70 | 71 | try { 72 | //Login to sap 73 | RfcDestination connection = connector.Login; 74 | 75 | //Set query'name and usergroup 76 | SAPQueryExtractor query = new SAPQueryExtractor(TestQuery, TestUserGroup); 77 | 78 | //Get SAP Query's input parameters 79 | SAPFieldItem param = query.GetSelectFields(connection).Where(p => !p.isIgnore).FirstOrDefault; 80 | param.Likes("*"); 81 | //set parameter value 82 | 83 | //Execute Query 84 | DataTable table = query.Invoke(connection, new List { param }); 85 | 86 | } catch (Exception ex) { 87 | Console.WriteLine(ex.Message); 88 | } 89 | ``` 90 | 91 | VB.Net 92 | 93 | ```vbnet 94 | Dim connector As New SAPConnector(TestDestination) 95 | 96 | Try 97 | 'Login to sap 98 | Dim connection As RfcDestination = connector.Login 99 | 100 | 'Set query'name and usergroup 101 | Dim query As New SAPQueryExtractor(TestQuery, TestUserGroup) 102 | 103 | 'Get SAP Query's input parameters 104 | Dim param As SAPFieldItem = query.GetSelectFields(connection).Where(Function(p) Not p.isIgnore).FirstOrDefault 105 | param.Likes("*") 'set parameter value 106 | 107 | 'Execute Query 108 | Dim table As DataTable = query.Invoke(connection, New List(Of SAPFieldItem) From {param}) 109 | 110 | Catch ex As Exception 111 | Console.WriteLine(ex.Message) 112 | End Try 113 | 114 | ``` 115 | -------------------------------------------------------------------------------- /SAPExtractorDotNET.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SAPExtractorDotNET", "SAPExtractorDotNET\SAPExtractorDotNET.vbproj", "{40DAB722-D636-44C3-806E-2D9FD2515206}" 5 | EndProject 6 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SAPExtractorDotNETTest", "SAPExtractorDotNETTest\SAPExtractorDotNETTest.vbproj", "{A870E26D-1A0A-4759-A1E6-77866B448D50}" 7 | EndProject 8 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "saploader", "saploader\saploader.vbproj", "{97B833F9-0624-4F7F-A782-F5F373107193}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {40DAB722-D636-44C3-806E-2D9FD2515206}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {40DAB722-D636-44C3-806E-2D9FD2515206}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {40DAB722-D636-44C3-806E-2D9FD2515206}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {40DAB722-D636-44C3-806E-2D9FD2515206}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {A870E26D-1A0A-4759-A1E6-77866B448D50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {A870E26D-1A0A-4759-A1E6-77866B448D50}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {A870E26D-1A0A-4759-A1E6-77866B448D50}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {A870E26D-1A0A-4759-A1E6-77866B448D50}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {97B833F9-0624-4F7F-A782-F5F373107193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {97B833F9-0624-4F7F-A782-F5F373107193}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {97B833F9-0624-4F7F-A782-F5F373107193}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {97B833F9-0624-4F7F-A782-F5F373107193}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/My Project/Application.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/My Project/Application.myapp: -------------------------------------------------------------------------------- 1 |  2 | 3 | false 4 | false 5 | 0 6 | true 7 | 0 8 | 1 9 | true 10 | 11 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Reflection 3 | Imports System.Runtime.InteropServices 4 | 5 | ' アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 6 | ' アセンブリに関連付けられている情報を変更するには、 7 | ' これらの属性値を変更してください。 8 | 9 | ' アセンブリ属性の値を確認します。 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 'このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります。 21 | 22 | 23 | ' アセンブリのバージョン情報は、以下の 4 つの値で構成されています: 24 | ' 25 | ' Major Version 26 | ' Minor Version 27 | ' Build Number 28 | ' Revision 29 | ' 30 | ' すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を 31 | ' 既定値にすることができます: 32 | ' 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/My Project/Resources.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | Imports System 15 | 16 | Namespace My.Resources 17 | 18 | 'このクラスは StronglyTypedResourceBuilder クラスが ResGen 19 | 'または Visual Studio のようなツールを使用して自動生成されました。 20 | 'メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に 21 | 'ResGen を実行し直すか、または VS プロジェクトをビルドし直します。 22 | ''' 23 | ''' ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。 24 | ''' 25 | _ 29 | Friend Module Resources 30 | 31 | Private resourceMan As Global.System.Resources.ResourceManager 32 | 33 | Private resourceCulture As Global.System.Globalization.CultureInfo 34 | 35 | ''' 36 | ''' このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。 37 | ''' 38 | _ 39 | Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager 40 | Get 41 | If Object.ReferenceEquals(resourceMan, Nothing) Then 42 | Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Resources", GetType(Resources).Assembly) 43 | resourceMan = temp 44 | End If 45 | Return resourceMan 46 | End Get 47 | End Property 48 | 49 | ''' 50 | ''' 厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、 51 | ''' 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。 52 | ''' 53 | _ 54 | Friend Property Culture() As Global.System.Globalization.CultureInfo 55 | Get 56 | Return resourceCulture 57 | End Get 58 | Set 59 | resourceCulture = value 60 | End Set 61 | End Property 62 | End Module 63 | End Namespace 64 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/My Project/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/My Project/Settings.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | Namespace My 16 | 17 | _ 20 | Partial Friend NotInheritable Class MySettings 21 | Inherits Global.System.Configuration.ApplicationSettingsBase 22 | 23 | Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) 24 | 25 | #Region "My.Settings 自動保存機能" 26 | #If _MyType = "WindowsForms" Then 27 | Private Shared addedHandler As Boolean 28 | 29 | Private Shared addedHandlerLockObject As New Object 30 | 31 | _ 32 | Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) 33 | If My.Application.SaveMySettingsOnExit Then 34 | My.Settings.Save() 35 | End If 36 | End Sub 37 | #End If 38 | #End Region 39 | 40 | Public Shared ReadOnly Property [Default]() As MySettings 41 | Get 42 | 43 | #If _MyType = "WindowsForms" Then 44 | If Not addedHandler Then 45 | SyncLock addedHandlerLockObject 46 | If Not addedHandler Then 47 | AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings 48 | addedHandler = True 49 | End If 50 | End SyncLock 51 | End If 52 | #End If 53 | Return defaultInstance 54 | End Get 55 | End Property 56 | End Class 57 | End Namespace 58 | 59 | Namespace My 60 | 61 | _ 64 | Friend Module MySettingsProperty 65 | 66 | _ 67 | Friend ReadOnly Property Settings() As Global.My.MySettings 68 | Get 69 | Return Global.My.MySettings.Default 70 | End Get 71 | End Property 72 | End Module 73 | End Namespace 74 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/My Project/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/SAPConnector.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.VisualBasic 2 | Imports SAP.Middleware.Connector 3 | 4 | Namespace SAPExtractorDotNET 5 | 6 | ''' 7 | ''' Create Connection to SAP.
8 | ''' implements Serializable to store in session. 9 | '''
10 | ''' 11 | 12 | Public Class SAPConnector 13 | 14 | Private _destination As String 15 | ''' destination name defined in web.config/app.config 16 | Public ReadOnly Property Destination As String 17 | Get 18 | Return _destination 19 | End Get 20 | End Property 21 | 22 | Private _isSilent As Boolean = False 23 | ''' is silent Login or not (silent mean user/password is already defined by destination) 24 | Public ReadOnly Property IsSilent As Boolean 25 | Get 26 | Return _isSilent 27 | End Get 28 | End Property 29 | 30 | Private _user As String = "" 31 | Public ReadOnly Property User() As String 32 | Get 33 | Return _user 34 | End Get 35 | End Property 36 | 37 | Private _password As String = "" 38 | Private Property Password() As String 39 | Get 40 | Dim bytePass As Byte() = Convert.FromBase64String(_password) 41 | Return System.Text.Encoding.Default.GetString(bytePass) 42 | End Get 43 | Set(value As String) 44 | Dim byted() As Byte = System.Text.Encoding.Default.GetBytes(value) 45 | _password = Convert.ToBase64String(byted) 46 | End Set 47 | End Property 48 | 49 | ''' 50 | ''' Create Connection only by RFC definition in web.config/app.config 51 | ''' 52 | ''' 53 | ''' 54 | Public Function Login() As RfcDestination 55 | Dim connection As RfcDestination = Nothing 56 | Dim destConnection As RfcDestination = RfcDestinationManager.GetDestination(Destination) 57 | If IsSilent Then 58 | connection = destConnection 59 | Else 60 | Dim userLogin As RfcCustomDestination = destConnection.CreateCustomDestination 61 | userLogin.User = User 62 | userLogin.Password = Password 63 | connection = userLogin 64 | End If 65 | 66 | If connection IsNot Nothing Then 67 | connection.Ping() 'confirm connection 68 | End If 69 | 70 | Return connection 71 | 72 | End Function 73 | 74 | Public Sub New(ByVal destination As String) 75 | _destination = destination 76 | _isSilent = True 77 | End Sub 78 | 79 | Public Sub New(ByVal destination As String, ByVal user As String, ByVal password As String) 80 | _destination = destination 81 | _isSilent = False 82 | _user = user 83 | Me.Password = password 84 | End Sub 85 | 86 | End Class 87 | 88 | End Namespace 89 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/SAPExtractorDotNET.vbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {40DAB722-D636-44C3-806E-2D9FD2515206} 8 | Library 9 | 10 | 11 | SAPExtractorDotNET 12 | 512 13 | Windows 14 | v4.0 15 | 16 | 17 | 18 | true 19 | full 20 | true 21 | true 22 | bin\Debug\ 23 | SAPExtractorDotNET.xml 24 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 25 | 26 | 27 | pdbonly 28 | false 29 | true 30 | true 31 | bin\Release\ 32 | SAPExtractorDotNET.xml 33 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 34 | 35 | 36 | On 37 | 38 | 39 | Binary 40 | 41 | 42 | Off 43 | 44 | 45 | On 46 | 47 | 48 | 49 | False 50 | SAPNco(x86)\rscp4n.dll 51 | 52 | 53 | False 54 | SAPNco(x86)\sapnco.dll 55 | 56 | 57 | False 58 | SAPNco(x86)\sapnco_utils.dll 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | True 82 | Application.myapp 83 | 84 | 85 | True 86 | True 87 | Resources.resx 88 | 89 | 90 | True 91 | Settings.settings 92 | True 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | VbMyResourcesResXFileCodeGenerator 102 | Resources.Designer.vb 103 | My.Resources 104 | Designer 105 | 106 | 107 | 108 | 109 | MyApplicationCodeGenerator 110 | Application.Designer.vb 111 | 112 | 113 | SettingsSingleFileGenerator 114 | My 115 | Settings.Designer.vb 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 132 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/SAPFieldItem.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.VisualBasic 2 | Imports SAP.Middleware.Connector 3 | 4 | Namespace SAPExtractorDotNET 5 | 6 | ''' 7 | ''' Select parameter to execute query 8 | ''' 9 | ''' 10 | Public Class SAPFieldItem 11 | 12 | ''' Unique id for field 13 | Public Property FieldId As String 14 | 15 | ''' Structure type of field 16 | Public Property FieldStructure As String 17 | 18 | ''' is field for range selection 19 | Public Property IsRangeField As Boolean = False 20 | 21 | ''' is system field or not 22 | Public Property isIgnore As Boolean = False 23 | 24 | ''' Text for field 25 | Public Property FieldText As String 26 | 27 | ''' Order no of field 28 | Public Property Order As Integer 29 | 30 | ''' Field type 31 | Public Property FieldType As String = "C" 32 | 33 | ''' Field size 34 | Public Property FieldSize As Integer 35 | 36 | ''' the group of field 37 | Public Property FieldGroup As String 38 | 39 | ''' is key field or not 40 | Public Property isKey As Boolean = False 41 | 42 | Public Property Operand As String = "EQ" 43 | Public Property IsExclude As Boolean = False 44 | Public Property Value As String = "" 45 | Public Property MaxValue As String = "" 46 | 47 | Public Sub New() 48 | End Sub 49 | 50 | Public Sub New(ByVal fieldId As String, Optional ByVal isRangeField As Boolean = False) 51 | Me.FieldId = fieldId 52 | Me.IsRangeField = isRangeField 53 | End Sub 54 | 55 | Public Shared Function createByStatement(ByVal statement As String, Optional ByVal isRangeField As Boolean = False) As SAPFieldItem 56 | Dim operands As String() = {"<>", ">=", "<=", "><", ">", "<", "="} 57 | Dim f As SAPFieldItem = Nothing 58 | 59 | For Each opr As String In operands 60 | If statement.IndexOf(opr) > -1 Then 61 | Dim keyValue As String() = statement.Split(opr) 62 | If keyValue.Count = 2 Then 63 | f = New SAPFieldItem(Trim(keyValue(0)), isRangeField) 64 | f.ComparesBy(opr, Trim(keyValue(1))) 65 | End If 66 | End If 67 | Next 68 | 69 | Return f 70 | 71 | End Function 72 | 73 | Public Shared Function createByQueryStructure(ByVal sapStructure As IRfcTable) As SAPFieldItem 74 | Dim f As New SAPFieldItem() 75 | f.FieldId = sapStructure.GetString("SPNAME") 76 | If f.FieldId.StartsWith("%") Then f.isIgnore = True 77 | 78 | f.FieldStructure = sapStructure.GetString("FNAME") 79 | f.IsRangeField = If(sapStructure.GetString("KIND") = "S", True, False) 80 | f.FieldText = sapStructure.GetString("FTEXT") 81 | 82 | f.FieldType = sapStructure.GetString("TYPE") 83 | f.FieldSize = CInt(sapStructure.GetString("LENGTH")) 84 | f.FieldGroup = sapStructure.GetString("RGROUP") 85 | 86 | Return f 87 | 88 | End Function 89 | 90 | Public Shared Function createByTableStructure(ByVal columns As Dictionary(Of String, String)) As SAPFieldItem 91 | Dim f As New SAPFieldItem() 92 | Dim getFieldValue = Function(name As String) As String 93 | If columns.ContainsKey(name) Then 94 | Return columns(name) 95 | Else 96 | Return Nothing 97 | End If 98 | End Function 99 | 100 | f.FieldId = getFieldValue("FIELDNAME") 101 | f.FieldStructure = getFieldValue("ROLLNAME") 102 | f.FieldType = getFieldValue("DATATYPE") 103 | f.FieldSize = getFieldValue("LENG") 104 | f.Order = getFieldValue("POSITION") 105 | f.isKey = If(String.IsNullOrEmpty(getFieldValue("KEYFLAG")), False, True) 106 | f.FieldText = getFieldValue("DDTEXT") 107 | 108 | Return f 109 | 110 | End Function 111 | 112 | Public Function IsEqualTo(ByVal value As String) As SAPFieldItem 113 | Me.Operand = "EQ" 114 | Me.Value = value 115 | Return Me 116 | End Function 117 | 118 | Public Function Likes(ByVal value As String) As SAPFieldItem 119 | Me.Operand = "CP" 120 | Me.Value = "*" + value + "*" 121 | Return Me 122 | End Function 123 | 124 | Public Function StartsWith(ByVal value As String) As SAPFieldItem 125 | Me.Operand = "CP" 126 | Me.Value = value + "*" 127 | Return Me 128 | End Function 129 | 130 | Public Function EndsWith(ByVal value As String) As SAPFieldItem 131 | Me.Operand = "CP" 132 | Me.Value = "*" + value 133 | Return Me 134 | End Function 135 | 136 | Public Function Matches(ByVal value As String) As SAPFieldItem 137 | Me.Operand = "CP" 138 | Me.Value = value 139 | Return Me 140 | End Function 141 | 142 | Public Function IsNotEqualTo(ByVal value As String) As SAPFieldItem 143 | Me.Operand = "NE" 144 | Me.Value = value 145 | Return Me 146 | End Function 147 | 148 | Public Function GreaterThan(ByVal value As String) As SAPFieldItem 149 | Me.Operand = "GT" 150 | Me.Value = value 151 | Return Me 152 | End Function 153 | 154 | Public Function LowerThan(ByVal value As String) As SAPFieldItem 155 | Me.Operand = "LT" 156 | Me.Value = value 157 | Return Me 158 | End Function 159 | 160 | Public Function GreaterEqual(ByVal value As String) As SAPFieldItem 161 | Me.Operand = "GE" 162 | Me.Value = value 163 | Return Me 164 | End Function 165 | 166 | Public Function LowerEqual(ByVal value As String) As SAPFieldItem 167 | Me.Operand = "LE" 168 | Me.Value = value 169 | Return Me 170 | End Function 171 | 172 | Public Function Between(ByVal value As String, ByVal maxValue As String) As SAPFieldItem 173 | If Not IsRangeField Then Throw New Exception("You can use between only when field is RangeField.") 174 | Me.Operand = "BT" 175 | Me.Value = value 176 | Me.MaxValue = maxValue 177 | Return Me 178 | End Function 179 | 180 | Public Function ComparesBy(ByVal opr As String, value As String) As SAPFieldItem 181 | Select Case opr.Trim 182 | Case "=" 183 | If value.Contains("*") Then 184 | Me.Matches(value) 185 | Else 186 | Me.IsEqualTo(value) 187 | End If 188 | Case "<>" 189 | Me.IsNotEqualTo(value) 190 | Case ">" 191 | Me.GreaterThan(value) 192 | Case "<" 193 | Me.LowerThan(value) 194 | Case ">=" 195 | Me.GreaterEqual(value) 196 | Case "<=" 197 | Me.LowerEqual(value) 198 | Case "><" 199 | Dim values As String() = value.Split(",") 200 | Me.Between(values(0), values(1)) 201 | End Select 202 | 203 | Return Me 204 | 205 | End Function 206 | 207 | Public Function makeWhere() As String 208 | Dim where As String = FieldId 209 | Dim wValue As String = makeWhereValue(Value) 210 | Select Case Operand 211 | Case "EQ" 212 | where += " = " + wValue 213 | Case "CP" 214 | where += " LIKE " + wValue 215 | Case "NE" 216 | where += " <> " + wValue 217 | Case "GT" 218 | where += " > " + wValue 219 | Case "LT" 220 | where += " < " + wValue 221 | Case "GE" 222 | where += " >= " + wValue 223 | Case "LE" 224 | where += " <= " + wValue 225 | Case "BT" 226 | where += " BETWEEN " + wValue + " AND " + makeWhereValue(MaxValue) 227 | End Select 228 | 229 | Return where 230 | 231 | End Function 232 | 233 | Private Function makeWhereValue(ByVal value As String) As String 234 | Dim result As String = escape(value) 235 | If FieldType = "C" Or FieldType = "CHAR" Then 236 | result = "'" + result + "'" 'round by single quote 237 | End If 238 | Return result 239 | End Function 240 | 241 | Public Shared Function escape(ByVal value As String) As String 242 | Dim escaped As String = value 243 | escaped = escaped.Replace(";", "").Replace("\", "\\").Replace("'", "''") 244 | escaped = escaped.Replace("%", "").Replace("*", "%") 245 | Return escaped 246 | End Function 247 | 248 | End Class 249 | 250 | End Namespace 251 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/SAPQueryExtractor.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.VisualBasic 2 | 3 | Imports SAP.Middleware.Connector 4 | Imports System.Threading.Tasks 5 | Imports System.Data 6 | Imports System.Text.RegularExpressions 7 | 8 | Namespace SAPExtractorDotNET 9 | 10 | ''' 11 | ''' Extract data from SAP Query 12 | ''' 13 | ''' 14 | Public Class SAPQueryExtractor 15 | Private Const RFC_TO_GET_QUERY_CATALOG As String = "RSAQ_REMOTE_QUERY_CATALOG" 16 | Private Const RFC_TO_GET_QUERY_FIELD As String = "RSAQ_REMOTE_QUERY_FIELDLIST" 17 | Private Const RFC_TO_EXECUTE_QUERY As String = "RSAQ_REMOTE_QUERY_CALL" 18 | Private Const DEFAULT_QUERY_AREA As String = "G" 19 | 20 | Private _queryArea As String = DEFAULT_QUERY_AREA 21 | Public ReadOnly Property QueryArea As String 22 | Get 23 | Return _queryArea 24 | End Get 25 | End Property 26 | 27 | Private _query As String = "" 28 | Public ReadOnly Property Query As String 29 | Get 30 | Return _query 31 | End Get 32 | End Property 33 | 34 | Private _userGroup As String = "" 35 | Public ReadOnly Property UserGroup As String 36 | Get 37 | Return _userGroup 38 | End Get 39 | End Property 40 | 41 | Public Property QueryVariant As String = "" 42 | Public Property QueryText As String = "" 43 | 44 | Public Sub New(ByVal queryArea As String, ByVal query As String, ByVal userGroup As String) 45 | _queryArea = queryArea 46 | _query = query 47 | _userGroup = userGroup 48 | End Sub 49 | 50 | Public Sub New(ByVal query As String, ByVal userGroup As String) 51 | _query = query 52 | _userGroup = userGroup 53 | End Sub 54 | 55 | ''' 56 | ''' Find SAP Query 57 | ''' 58 | ''' 59 | ''' 60 | ''' 61 | ''' 62 | ''' 63 | Public Shared Function Find(ByVal destination As RfcDestination, Optional ByVal queryName As String = "", Optional ByVal userGroup As String = "") As List(Of SAPQueryExtractor) 64 | Dim result As New List(Of SAPQueryExtractor) 65 | Dim func As IRfcFunction = destination.Repository.CreateFunction(RFC_TO_GET_QUERY_CATALOG) 66 | func.SetValue("WORKSPACE", DEFAULT_QUERY_AREA) 67 | func.SetValue("GENERIC_QUERYNAME", If(String.IsNullOrEmpty(queryName), "*", queryName)) 68 | func.SetValue("GENERIC_USERGROUP", If(String.IsNullOrEmpty(userGroup), "*", userGroup)) 69 | 70 | func.Invoke(destination) 71 | 72 | Dim rfcTable As IRfcTable = func.GetTable("QUERYCATALOG") 73 | 74 | For i As Integer = 0 To rfcTable.Count - 1 75 | rfcTable.CurrentIndex = i 76 | Dim q As New SAPQueryExtractor(rfcTable.GetValue("QUERY"), rfcTable.GetValue("NUM")) 77 | q.QueryText = rfcTable.GetValue("QTEXT") 78 | result.Add(q) 79 | Next 80 | 81 | Return result 82 | 83 | End Function 84 | 85 | Public Function GetSelectFields(ByVal destination As RfcDestination) As List(Of SAPFieldItem) 86 | Dim fields As New List(Of SAPFieldItem) 87 | 88 | Dim func As IRfcFunction = destination.Repository.CreateFunction(RFC_TO_GET_QUERY_FIELD) 89 | func.SetValue("WORKSPACE", QueryArea) 90 | func.SetValue("QUERY", Query) 91 | func.SetValue("USERGROUP", UserGroup) 92 | 93 | func.Invoke(destination) 94 | 95 | Dim rfcTable As IRfcTable = func.GetTable("SEL_FIELDS") 96 | 97 | For i As Integer = 0 To rfcTable.Count - 1 98 | rfcTable.CurrentIndex = i 99 | Dim f As SAPFieldItem = SAPFieldItem.createByQueryStructure(rfcTable) 100 | f.Order = i 101 | fields.Add(f) 102 | Next 103 | 104 | Return fields 105 | 106 | End Function 107 | 108 | ''' 109 | ''' Extract data from SAP Query 110 | ''' 111 | ''' 112 | ''' 113 | ''' 114 | ''' 115 | Public Function Invoke(ByVal destination As RfcDestination, Optional ByVal fields As List(Of SAPFieldItem) = Nothing) As DataTable 116 | Dim result As New DataTable 117 | Dim filters As List(Of SAPFieldItem) = fields 118 | 119 | 'no-variant and no-filters cause NO_SELECTION exception. so if input parameter exist , set * to it. 120 | If fields Is Nothing OrElse fields.Count = 0 Then 121 | If String.IsNullOrEmpty(QueryVariant) Then 122 | Dim param As SAPFieldItem = GetSelectFields(destination).Where(Function(p) Not p.isIgnore).FirstOrDefault 123 | If param IsNot Nothing Then 124 | If param.FieldType = "D" Then 125 | filters = New List(Of SAPFieldItem) From {param.GreaterThan("10000101")} 126 | Else 127 | filters = New List(Of SAPFieldItem) From {param.Matches("*")} 128 | End If 129 | End If 130 | End If 131 | Else 132 | For i As Integer = 0 To filters.Count - 1 133 | If String.IsNullOrEmpty(filters(i).FieldId) Then 134 | filters(i).FieldId = "SP$" + (i + 1).ToString.PadLeft(5, "0") 'set default parameter name 135 | End If 136 | Next 137 | End If 138 | 139 | Dim func As IRfcFunction = destination.Repository.CreateFunction(RFC_TO_EXECUTE_QUERY) 140 | func.SetValue("WORKSPACE", QueryArea) 141 | func.SetValue("QUERY", Query) 142 | func.SetValue("USERGROUP", UserGroup) 143 | func.SetValue("DATA_TO_MEMORY", "X") 144 | func.SetValue("EXTERNAL_PRESENTATION", "Z") 'convert sap currency to external (without comma format) 145 | 146 | If Not String.IsNullOrEmpty(QueryVariant) Then 147 | func.SetValue("VARIANT", QueryVariant) 148 | End If 149 | 150 | If filters IsNot Nothing AndAlso filters.Count > 0 Then 151 | Dim selections As IRfcTable = func.GetTable("SELECTION_TABLE") 152 | For Each field As SAPFieldItem In filters 153 | selections.Append() 154 | selections.CurrentIndex = selections.Count - 1 155 | selections.SetValue("SELNAME", field.FieldId) 156 | selections.SetValue("KIND", If(field.IsRangeField, "S", "P")) 157 | selections.SetValue("SIGN", If(field.IsExclude, "E", "I")) 158 | selections.SetValue("OPTION", field.Operand) 159 | selections.SetValue("LOW", field.Value) 160 | If field.IsRangeField Then 161 | selections.SetValue("HIGH", field.MaxValue) 162 | End If 163 | Next 164 | End If 165 | 166 | func.Invoke(destination) 167 | 168 | 'read type and make columns 169 | Dim struct As IRfcTable = func.GetTable("LISTDESC") 170 | For i As Long = 0 To struct.Count - 1 171 | struct.CurrentIndex = i 172 | Dim column As New DataColumn(struct.GetString("FNAME")) 173 | If result.Columns.Contains(column.ColumnName) Then 174 | column.ColumnName = column.ColumnName + "__" + struct.GetString("FPOS") ' for duplicate type 175 | End If 176 | 177 | column.Caption = struct.GetString("FDESC") 178 | column.MaxLength = struct.GetInt("FOLEN") 179 | result.Columns.Add(column) 180 | 181 | Next 182 | 183 | 'read data 184 | Dim lines As New List(Of LineData) 185 | Dim ldata As IRfcTable = func.GetTable("LDATA") 186 | For i As Long = 0 To ldata.Count - 1 187 | ldata.CurrentIndex = i 188 | Dim line As New LineData(i, ldata.GetString("LINE")) 189 | lines.Add(line) 190 | Next 191 | 192 | 'returned data is like csv data. so split it 193 | Parallel.ForEach(lines, Sub(r As LineData) r.Split()) 194 | 195 | Dim index As Integer = 0 196 | Dim bound As Integer = result.Columns.Count 197 | Dim rowValues As New List(Of String) 198 | 'read each splited element into datarow 199 | For Each item As LineData In lines 200 | For Each element As String In item.Elements 201 | If index < bound Then 202 | rowValues.Add(element) 203 | Else 204 | Dim row As DataRow = result.NewRow() 205 | For i As Integer = 0 To rowValues.Count - 1 206 | row(i) = rowValues(i) 207 | Next 208 | result.Rows.Add(row) 209 | rowValues.Clear() 210 | rowValues.Add(element) 211 | index = 0 212 | End If 213 | index += 1 214 | 215 | Next 216 | Next 217 | 218 | 'add last row 219 | If rowValues.Count > 0 Then 220 | Dim lastRow As DataRow = result.NewRow() 221 | For i As Integer = 0 To rowValues.Count - 1 222 | lastRow(i) = rowValues(i) 223 | Next 224 | result.Rows.Add(lastRow) 225 | End If 226 | 227 | Return result 228 | 229 | End Function 230 | 231 | End Class 232 | 233 | ''' 234 | ''' to read rfc returned string 235 | ''' 236 | ''' 237 | Public Class LineData 238 | Public Property Index As Long = 0 239 | Public Property Line As String = "" 240 | Public Property Elements As New List(Of String) 241 | 242 | Public Const LENGTH_PART_SIZE As Integer = 3 243 | 244 | Public Sub New(ByVal index As Long, ByVal line As String) 245 | Me.Index = index 246 | Me.Line = line 247 | End Sub 248 | 249 | Public Sub Split() 250 | Dim index As Integer = 0 251 | 252 | 'length between index and line-end has to be shorter than length-part size(if not, there is no content to be read). 253 | While index < Me.Line.Length - LENGTH_PART_SIZE 254 | Dim nextAndContent As KeyValuePair(Of Integer, String) = readLine(index, Me.Line) 255 | index = nextAndContent.Key 256 | Elements.Add(nextAndContent.Value) 257 | End While 258 | 259 | End Sub 260 | 261 | Private Function readLine(ByVal index As Integer, ByVal line As String) As KeyValuePair(Of Integer, String) 262 | Dim head As Integer = index 263 | 264 | Dim lengthPart As String = line.Substring(head, LENGTH_PART_SIZE) 265 | Dim length As Integer = -1 266 | Dim content As String = "" 267 | 268 | If Integer.TryParse(lengthPart, length) Then 269 | head += LENGTH_PART_SIZE + 1 270 | If head + length <= line.Length Then 271 | content = line.Substring(head, length) 272 | Else 273 | Throw New Exception("query data is too short than directed content length. @line " + Me.Index.ToString) 274 | End If 275 | Else 276 | Throw New Exception("Unexpected query data. it doesn't have content length part. @line " + Me.Index.ToString) 277 | End If 278 | 279 | Return New KeyValuePair(Of Integer, String)(head + length + 1, content) ' Next head position and content 280 | 281 | End Function 282 | 283 | Public Overrides Function ToString() As String 284 | Return Me.Line 285 | End Function 286 | 287 | End Class 288 | 289 | 290 | End Namespace 291 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/SAPTableExtractor.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.VisualBasic 2 | 3 | Imports SAP.Middleware.Connector 4 | Imports System.Threading.Tasks 5 | Imports System.Data 6 | Imports System.Globalization 7 | 8 | Namespace SAPExtractorDotNET 9 | 10 | ''' 11 | ''' Extract data from SAP Table 12 | ''' 13 | ''' 14 | Public Class SAPTableExtractor 15 | 16 | 'RFC_READ_TABLE and BBP_RFC_READ_TABLE has some bug (mainly when extracting data from huge or including number fields table). 17 | 'SAP disabled /SDF/GET_GENERIC_APO_TABLE ... 18 | 'Private Const RFC_TO_GET_TABLE As String = "/SDF/GET_GENERIC_APO_TABLE" 19 | 20 | Private Const RFC_TO_GET_TABLE As String = "RFC_READ_TABLE" 21 | 22 | Private Const TABLE_TABLE As String = "DD02T" 23 | Private Const COLUMN_DEFINE_TABLE As String = "DD03M" 24 | 25 | Private Const MaxRowByteLength As Integer = 512 26 | Private Const BasicEscapes As String = ";'\" 27 | 28 | Private _table As String = "" 29 | Public ReadOnly Property Table As String 30 | Get 31 | Return _table 32 | End Get 33 | End Property 34 | 35 | Public Property TableText As String 36 | 37 | Public Sub New(ByVal tableName As String) 38 | Me._table = tableName 39 | End Sub 40 | 41 | ''' 42 | ''' Find Table 43 | ''' 44 | ''' 45 | ''' 46 | ''' 47 | ''' 48 | Public Shared Function Find(ByVal destination As RfcDestination, Optional ByVal tableName As String = "") As List(Of SAPTableExtractor) 49 | Dim result As New List(Of SAPTableExtractor) 50 | 51 | Dim fields As New List(Of SAPFieldItem) 52 | For Each columnName As String In {"TABNAME", "DDTEXT"} 53 | fields.Add(New SAPFieldItem(columnName)) 54 | Next 55 | 56 | Dim options As New List(Of SAPFieldItem) 57 | options.Add(New SAPFieldItem("DDLANGUAGE").IsEqualTo(CultureInfo.CurrentCulture.TwoLetterISOLanguageName.Substring(0, 1).ToUpper)) 58 | options.Add(New SAPFieldItem("AS4LOCAL").IsEqualTo("A")) 59 | If Not String.IsNullOrEmpty(tableName) Then 60 | If tableName.Contains("*") Then 61 | options.Add(New SAPFieldItem("TABNAME").Matches(tableName)) 62 | Else 63 | options.Add(New SAPFieldItem("TABNAME").IsEqualTo(tableName)) 64 | End If 65 | End If 66 | 67 | Dim tables As List(Of Dictionary(Of String, String)) = SAPTableExtractor.Invoke(destination, TABLE_TABLE, fields, options) 68 | tables = tables.OrderBy(Function(d) d("TABNAME")).ToList 69 | 70 | For Each table As Dictionary(Of String, String) In tables 71 | Dim t As New SAPTableExtractor(table("TABNAME")) 72 | t.TableText = table("DDTEXT") 73 | result.Add(t) 74 | Next 75 | 76 | Return result 77 | 78 | End Function 79 | 80 | ''' 81 | ''' Get table's columns definition. 82 | ''' 83 | ''' 84 | ''' 85 | ''' Column definitions are taken from DD03M 86 | Public Function GetColumnFields(ByVal destination As RfcDestination) As List(Of SAPFieldItem) 87 | 88 | Dim fields As New List(Of SAPFieldItem) 89 | Dim options As New List(Of SAPFieldItem) 90 | 91 | fields.Add(New SAPFieldItem("FIELDNAME")) 92 | fields.Add(New SAPFieldItem("ROLLNAME")) 93 | fields.Add(New SAPFieldItem("DATATYPE")) 94 | fields.Add(New SAPFieldItem("LENG")) 95 | fields.Add(New SAPFieldItem("POSITION")) 96 | fields.Add(New SAPFieldItem("KEYFLAG")) 97 | fields.Add(New SAPFieldItem("DDTEXT")) 98 | 99 | options.Add(New SAPFieldItem("TABNAME").IsEqualTo(Table)) 100 | options.Add(New SAPFieldItem("FLDSTAT").IsEqualTo("A")) 101 | options.Add(New SAPFieldItem("DDLANGUAGE").IsEqualTo(CultureInfo.CurrentCulture.TwoLetterISOLanguageName.Substring(0, 1).ToUpper)) 102 | 103 | Dim columnDefines As List(Of Dictionary(Of String, String)) = Invoke(destination, COLUMN_DEFINE_TABLE, fields, options) 104 | columnDefines = columnDefines.OrderBy(Function(d) d("POSITION")).ToList 105 | 106 | Dim result As New List(Of SAPFieldItem) 107 | For Each cDefine As Dictionary(Of String, String) In columnDefines 108 | Dim f As SAPFieldItem = SAPFieldItem.createByTableStructure(cDefine) 109 | result.Add(f) 110 | Next 111 | 112 | Return result 113 | 114 | End Function 115 | 116 | ''' 117 | ''' Get SAP Table data.
118 | ''' If condition is Nothing, then get all columns of table. 119 | '''
120 | ''' 121 | ''' 122 | ''' 123 | ''' 124 | ''' 125 | Public Function Invoke(ByVal destination As RfcDestination, ByVal fields As List(Of SAPFieldItem), ByVal options As List(Of SAPFieldItem)) As DataTable 126 | 127 | Dim result As New DataTable 128 | Dim rows As List(Of Dictionary(Of String, String)) = Nothing 129 | Dim localFields As List(Of SAPFieldItem) = fields 130 | Dim rowByteLength As Integer = 0 131 | If fields Is Nothing OrElse fields.Count = 0 Then 132 | 'get all columns 133 | localFields = GetColumnFields(destination) 134 | localFields.ForEach(Sub(f) rowByteLength += f.FieldSize) 135 | End If 136 | 137 | 'RFC has byte-length restriction of row. So if there are too many columns, splite it and merge result after. 138 | If rowByteLength > MaxRowByteLength Then 139 | 140 | Dim columnDefines As List(Of SAPFieldItem) = GetColumnFields(destination) 141 | Dim keys As List(Of SAPFieldItem) = columnDefines.Where(Function(c) c.isKey).ToList 142 | Dim keySize As Integer = 0 143 | keys.ForEach(Sub(k) k.isIgnore = True) 144 | keys.ForEach(Sub(k) keySize += k.FieldSize) 145 | 146 | 'make row's primary key string 147 | Dim makeKey = Function(row As Dictionary(Of String, String)) As String 148 | Dim localKeies As New List(Of String) 149 | keys.ForEach(Sub(k) localKeies.Add(row(k.FieldId))) 150 | Return String.Join("__", localKeies) 151 | End Function 152 | 153 | 'split columns and merge it by primary after. 154 | Dim splitedFields As New List(Of List(Of SAPFieldItem)) 155 | Dim limit As Integer = MaxRowByteLength - keySize 156 | Dim splitedTotal As Integer = 0 157 | Dim splited As New List(Of SAPFieldItem) 158 | 159 | For Each columns In columnDefines 160 | 161 | If splitedTotal + columns.FieldSize > limit Then 162 | Dim fieldSet As New List(Of SAPFieldItem)(keys) 163 | fieldSet.AddRange(splited) 164 | splitedFields.Add(fieldSet) 165 | splited.Clear() 166 | splitedTotal = 0 167 | End If 168 | 169 | If Not columns.isIgnore Then 170 | splited.Add(columns) 171 | splitedTotal += columns.FieldSize 172 | End If 173 | 174 | Next 175 | 176 | If splited.Count > 0 Then 177 | Dim fieldSet As New List(Of SAPFieldItem)(keys) 178 | fieldSet.AddRange(splited) 179 | splitedFields.Add(fieldSet) 180 | End If 181 | 182 | Dim tasks As New List(Of Task(Of Dictionary(Of String, Dictionary(Of String, String)))) 183 | splitedFields.ForEach(Sub(sc) 184 | tasks.Add(New Task(Of Dictionary(Of String, Dictionary(Of String, String)))( 185 | Function() 186 | Dim tResult As List(Of Dictionary(Of String, String)) = Invoke(destination, Table, sc, options) 187 | Return tResult.ToDictionary(Of String, Dictionary(Of String, String))(Function(tr) makeKey(tr), Function(tr) tr) 188 | End Function 189 | )) 190 | End Sub) 191 | 192 | Dim taskRuns = tasks.ToArray 193 | Array.ForEach(taskRuns, Sub(t) t.Start()) 194 | task.WaitAll(taskRuns) 195 | 196 | Dim merged As New Dictionary(Of String, Dictionary(Of String, String)) 197 | 198 | 'merge by primary key 199 | For Each runed In taskRuns 200 | If runed.IsCompleted Then 201 | For Each tResult In runed.Result 202 | If Not merged.ContainsKey(tResult.Key) Then 203 | merged.Add(tResult.Key, tResult.Value) 204 | Else 205 | For Each item In tResult.Value 206 | If Not merged(tResult.Key).ContainsKey(item.Key) Then merged(tResult.Key).Add(item.Key, item.Value) 207 | Next 208 | End If 209 | Next 210 | End If 211 | Next 212 | 213 | rows = merged.Values.ToList 214 | 215 | Else 216 | rows = Invoke(destination, Table, localFields, options) 217 | 218 | End If 219 | 220 | For Each cond As SAPFieldItem In localFields 221 | Dim column As New DataColumn(cond.FieldId) 222 | column.Caption = cond.FieldText 223 | result.Columns.Add(column) 224 | Next 225 | 226 | For Each row In rows 227 | Dim addRow As DataRow = result.NewRow 228 | For Each column As DataColumn In result.Columns 229 | If row.ContainsKey(column.ColumnName) Then 230 | addRow(column.ColumnName) = row(column.ColumnName) 231 | End If 232 | Next 233 | result.Rows.Add(addRow) 234 | Next 235 | 236 | Return result 237 | 238 | End Function 239 | 240 | Private Shared Function Invoke(ByVal destination As RfcDestination, ByVal table As String, ByVal fields As List(Of SAPFieldItem), ByVal options As List(Of SAPFieldItem)) 241 | 242 | Dim func As IRfcFunction = destination.Repository.CreateFunction(RFC_TO_GET_TABLE) 243 | 244 | 'set fields 245 | If fields IsNot Nothing Then 246 | Dim fs As IRfcTable = func.GetTable("FIELDS") 247 | For i As Integer = 0 To fields.Count - 1 248 | fs.Append() 249 | fs.CurrentIndex = i 250 | fs.SetValue("FIELDNAME", fields(i).FieldId) 251 | Next 252 | End If 253 | 254 | 'set options 255 | If options IsNot Nothing Then 256 | Dim opts As IRfcTable = func.GetTable("OPTIONS") 257 | For i As Integer = 0 To options.Count - 1 258 | opts.Append() 259 | opts.CurrentIndex = i 260 | opts.SetValue("TEXT", If(i > 0, " AND ", "") + options(i).makeWhere) 261 | Next 262 | End If 263 | 264 | func.SetValue("QUERY_TABLE", SAPFieldItem.escape(table)) 265 | 266 | func.Invoke(destination) 267 | 268 | Dim result As New List(Of Dictionary(Of String, String)) 269 | 270 | Dim index As Integer = 0 271 | Dim struct As IRfcTable = func.GetTable("FIELDS") 272 | Dim columns As New Dictionary(Of String, Integer) 273 | 274 | For i As Integer = 0 To struct.Count - 1 275 | struct.CurrentIndex = i 276 | columns.Add(struct.GetString("FIELDNAME"), struct.GetInt("LENGTH")) 277 | Next 278 | 279 | Dim data As IRfcTable = func.GetTable("DATA") 280 | For i As Long = 0 To data.Count - 1 281 | data.CurrentIndex = i 282 | Dim line = data.GetString("WA") 283 | 284 | Dim row As New Dictionary(Of String, String) 285 | Dim position As Integer = 0 286 | For Each c In columns 287 | If position + c.Value <= line.Length Then 288 | row.Add(c.Key, line.Substring(position, c.Value).Trim) 289 | ElseIf position <= line.Length Then 290 | row.Add(c.Key, line.Substring(position).Trim) 291 | Else 292 | row.Add(c.Key, String.Empty) 293 | End If 294 | position += c.Value 295 | Next 296 | result.Add(row) 297 | Next 298 | 299 | Return result 300 | 301 | End Function 302 | 303 | Public Function Invoke(ByVal destination As RfcDestination) As DataTable 304 | Return Invoke(destination, {}) 305 | End Function 306 | 307 | Public Function Invoke(ByVal destination As RfcDestination, fields As String(), ByVal ParamArray options As SAPFieldItem()) As DataTable 308 | Return Invoke(destination, New List(Of String)(fields), options) 309 | End Function 310 | 311 | Public Function Invoke(ByVal destination As RfcDestination, fields As List(Of String), ByVal ParamArray options As SAPFieldItem()) As DataTable 312 | Dim fieldItems As New List(Of SAPFieldItem) 313 | 314 | For Each field As String In fields 315 | fieldItems.Add(New SAPFieldItem(field)) 316 | Next 317 | 318 | Return Invoke(destination, fieldItems, New List(Of SAPFieldItem)(options)) 319 | 320 | End Function 321 | 322 | End Class 323 | 324 | End Namespace 325 | 326 | 327 | -------------------------------------------------------------------------------- /SAPExtractorDotNET/lib/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icoxfog417/SAPExtractorDotNET/866fc823c97c4141a666279eb0a3667eb94c1b76/SAPExtractorDotNET/lib/.keep -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/My Project/Application.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/My Project/Application.myapp: -------------------------------------------------------------------------------- 1 |  2 | 3 | false 4 | false 5 | 0 6 | true 7 | 0 8 | 1 9 | true 10 | 11 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Reflection 3 | Imports System.Runtime.InteropServices 4 | 5 | ' アセンブリに関する情報は、次の属性のセットを通して制御されます。 6 | ' アセンブリに関連付けられている情報を変更するには、 7 | ' これらの属性値を変更してください。 8 | 9 | ' アセンブリ属性の値を確認します。 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 'このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります。 21 | 22 | 23 | ' アセンブリのバージョン情報は、以下の 4 つの値で構成されています: 24 | ' 25 | ' Major Version 26 | ' Minor Version 27 | ' Build Number 28 | ' Revision 29 | ' 30 | ' すべての値を指定するか、以下のように '*' を使用してビルドおよびリビジョン番号を 31 | ' 既定値にすることができます: 32 | ' 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/My Project/Resources.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | Imports System 15 | 16 | Namespace My.Resources 17 | 18 | 'このクラスは StronglyTypedResourceBuilder クラスが ResGen 19 | 'または Visual Studio のようなツールを使用して自動生成されました。 20 | 'メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に 21 | 'ResGen を実行し直すか、または VS プロジェクトをビルドし直します。 22 | ''' 23 | ''' ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。 24 | ''' 25 | _ 29 | Friend Module Resources 30 | 31 | Private resourceMan As Global.System.Resources.ResourceManager 32 | 33 | Private resourceCulture As Global.System.Globalization.CultureInfo 34 | 35 | ''' 36 | ''' このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。 37 | ''' 38 | _ 39 | Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager 40 | Get 41 | If Object.ReferenceEquals(resourceMan, Nothing) Then 42 | Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("SAPExtractorDotNETTest.Resources", GetType(Resources).Assembly) 43 | resourceMan = temp 44 | End If 45 | Return resourceMan 46 | End Get 47 | End Property 48 | 49 | ''' 50 | ''' 厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、 51 | ''' 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。 52 | ''' 53 | _ 54 | Friend Property Culture() As Global.System.Globalization.CultureInfo 55 | Get 56 | Return resourceCulture 57 | End Get 58 | Set 59 | resourceCulture = value 60 | End Set 61 | End Property 62 | End Module 63 | End Namespace 64 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/My Project/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/My Project/Settings.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | Namespace My 16 | 17 | _ 20 | Partial Friend NotInheritable Class MySettings 21 | Inherits Global.System.Configuration.ApplicationSettingsBase 22 | 23 | Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) 24 | 25 | #Region "My.Settings 自動保存機能" 26 | #If _MyType = "WindowsForms" Then 27 | Private Shared addedHandler As Boolean 28 | 29 | Private Shared addedHandlerLockObject As New Object 30 | 31 | _ 32 | Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) 33 | If My.Application.SaveMySettingsOnExit Then 34 | My.Settings.Save() 35 | End If 36 | End Sub 37 | #End If 38 | #End Region 39 | 40 | Public Shared ReadOnly Property [Default]() As MySettings 41 | Get 42 | 43 | #If _MyType = "WindowsForms" Then 44 | If Not addedHandler Then 45 | SyncLock addedHandlerLockObject 46 | If Not addedHandler Then 47 | AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings 48 | addedHandler = True 49 | End If 50 | End SyncLock 51 | End If 52 | #End If 53 | Return defaultInstance 54 | End Get 55 | End Property 56 | End Class 57 | End Namespace 58 | 59 | Namespace My 60 | 61 | _ 64 | Friend Module MySettingsProperty 65 | 66 | _ 67 | Friend ReadOnly Property Settings() As Global.SAPExtractorDotNETTest.My.MySettings 68 | Get 69 | Return Global.SAPExtractorDotNETTest.My.MySettings.Default 70 | End Get 71 | End Property 72 | End Module 73 | End Namespace 74 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/My Project/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/QueryExtraction.vb: -------------------------------------------------------------------------------- 1 | Imports System.Text 2 | Imports Microsoft.VisualStudio.TestTools.UnitTesting 3 | Imports SAP.Middleware.Connector 4 | Imports SAPExtractorDotNET 5 | Imports System.Configuration 6 | Imports SAPExtractorDotNETTest.Util 7 | 8 | 9 | 10 | Public Class QueryExtraction 11 | 12 | Private Const TestDestination As String = "SILENT_LOGIN" 13 | 14 | Public ReadOnly Property TestQuery As String 15 | Get 16 | Return ConfigurationManager.AppSettings("testQuery") 17 | End Get 18 | End Property 19 | 20 | Public ReadOnly Property TestUserGroup As String 21 | Get 22 | Return ConfigurationManager.AppSettings("testUserGroup") 23 | End Get 24 | End Property 25 | 26 | 27 | Public Sub MakeFieldByStatement() 28 | 29 | Dim f1 As SAPFieldItem = SAPFieldItem.createByStatement("BUKRS = 1000") 30 | Assert.AreEqual("BUKRS", f1.FieldId) 31 | Assert.AreEqual("EQ", f1.Operand) 32 | Assert.AreEqual("1000", f1.Value) 33 | 34 | End Sub 35 | 36 | 37 | Public Sub FindQuery() 38 | Dim connector As New SAPConnector(TestDestination) 39 | 40 | Try 41 | Dim connection As RfcDestination = connector.Login 42 | Dim list As List(Of SAPQueryExtractor) = SAPQueryExtractor.Find(connection, "Y*", "Y*") 43 | 44 | For i As Integer = 0 To If(list.Count > 10, 10, list.Count) - 1 45 | Dim q = list(i) 46 | Console.WriteLine(q.UserGroup + "/" + q.Query + ":" + q.QueryText) 47 | Next 48 | 49 | Catch ex As Exception 50 | Console.WriteLine(ex.Message) 51 | Assert.Fail() 52 | End Try 53 | 54 | End Sub 55 | 56 | 57 | Public Sub GetQueryParameters() 58 | 59 | Dim connector As New SAPConnector(TestDestination) 60 | 61 | Try 62 | Dim connection As RfcDestination = connector.Login 63 | 64 | Dim query As New SAPQueryExtractor(TestQuery, TestUserGroup) 65 | Dim queryParams As List(Of SAPFieldItem) = query.GetSelectFields(connection) 66 | 67 | ResultWriter.Write(queryParams) 68 | 69 | Catch ex As Exception 70 | Console.WriteLine(ex.Message) 71 | Assert.Fail() 72 | End Try 73 | 74 | End Sub 75 | 76 | 77 | Public Sub ExtractQuery() 78 | 79 | Dim connector As New SAPConnector(TestDestination) 80 | 81 | Try 82 | Dim connection As RfcDestination = connector.Login 83 | 84 | Dim query As New SAPQueryExtractor(TestQuery, TestUserGroup) 85 | Dim table As DataTable = query.Invoke(connection) 86 | ResultWriter.Write(table) 87 | 88 | Catch ex As Exception 89 | Console.WriteLine(ex.Message) 90 | Assert.Fail() 91 | End Try 92 | 93 | End Sub 94 | 95 | 96 | Public Sub ExtractQueryWithCriteria() 97 | 98 | Dim connector As New SAPConnector(TestDestination) 99 | 100 | Try 101 | Dim connection As RfcDestination = connector.Login 102 | 103 | Dim query As New SAPQueryExtractor(TestQuery, TestUserGroup) 104 | 105 | Dim param As SAPFieldItem = SAPFieldItem.createByStatement(">=1000/1/1", True) 106 | Dim table As DataTable = query.Invoke(connection, New List(Of SAPFieldItem) From {param}) 107 | ResultWriter.Write(table) 108 | 109 | Catch ex As Exception 110 | Console.WriteLine(ex.Message) 111 | Assert.Fail() 112 | End Try 113 | 114 | End Sub 115 | 116 | 117 | Public Sub LineDataSeparation() 118 | Dim queryData As New List(Of String) 119 | queryData.Add("000000000000000001") 120 | queryData.Add("20010101") 121 | queryData.Add("") 122 | queryData.Add("") 123 | 124 | queryData.Add("A00000000000000001") 125 | queryData.Add("2002/01/01:") 126 | queryData.Add("5:00000,") 127 | queryData.Add("XX") 128 | 129 | queryData.Add("B00000000000000001") 130 | queryData.Add("20030101") 131 | queryData.Add("025:aaa, 000: aaaa, 022: bbbb;") 'most complicated case 132 | queryData.Add("X") 133 | 134 | Dim queryLine As String = "" 135 | For Each el In queryData 136 | If Not String.IsNullOrEmpty(queryLine) Then 137 | queryLine += "," 138 | End If 139 | queryLine += el.Length.ToString.PadLeft(3, "0") + ":" + el 140 | Next 141 | queryLine += ";/" 142 | Console.WriteLine(queryLine) 143 | 144 | Dim line As New LineData(0, queryLine) 145 | line.Split() 146 | 147 | For i As Integer = 0 To line.Elements.Count - 1 148 | Console.WriteLine(line.Elements(i)) 149 | Assert.AreEqual(queryData(i), line.Elements(i)) 150 | Next 151 | 152 | End Sub 153 | 154 | End Class -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/ResultWriter.vb: -------------------------------------------------------------------------------- 1 | Imports SAPExtractorDotNET 2 | 3 | Namespace Util 4 | 5 | ''' 6 | ''' Utility Class to display result(Dictionary,DataTable) 7 | ''' 8 | ''' 9 | Public Class ResultWriter 10 | 11 | Public Shared Sub Write(ByVal table As DataTable, Optional ByVal maxCount As Integer = 10) 12 | 13 | Dim count As Integer = 0 14 | Dim columns = (From col As DataColumn In table.Columns).ToList 15 | For Each row As DataRow In table.Rows 16 | Dim line As String = "" 17 | columns.ForEach(Sub(c) line += c.ColumnName + ":" + row(c.ColumnName) + " ") 18 | Console.WriteLine(Trim(line)) 19 | If count > 10 Then Exit For 20 | count += 1 21 | Next 22 | 23 | End Sub 24 | 25 | Public Shared Sub Write(ByVal fields As List(Of SAPFieldItem)) 26 | 27 | For Each f As SAPFieldItem In fields 28 | Console.WriteLine(f.FieldId + ":" + f.FieldText) 29 | Next 30 | 31 | End Sub 32 | 33 | End Class 34 | 35 | End Namespace 36 | 37 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/SAPExtractorDotNETTest.vbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {A870E26D-1A0A-4759-A1E6-77866B448D50} 7 | Library 8 | SAPExtractorDotNETTest 9 | SAPExtractorDotNETTest 10 | 512 11 | Windows 12 | v4.0 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{F184B08F-C81C-45F6-A57F-5ABD9991F28F} 14 | App.Config 15 | 10.0 16 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 17 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 18 | False 19 | UnitTest 20 | 21 | 22 | 23 | true 24 | full 25 | true 26 | true 27 | bin\Debug\ 28 | SAPExtractorDotNETTest.xml 29 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 30 | 31 | 32 | pdbonly 33 | false 34 | true 35 | true 36 | bin\Release\ 37 | SAPExtractorDotNETTest.xml 38 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 39 | 40 | 41 | On 42 | 43 | 44 | Binary 45 | 46 | 47 | Off 48 | 49 | 50 | On 51 | 52 | 53 | 54 | False 55 | ..\SAPExtractorDotNET\lib\rscp4n.dll 56 | 57 | 58 | False 59 | ..\SAPExtractorDotNET\lib\sapnco.dll 60 | 61 | 62 | False 63 | ..\SAPExtractorDotNET\lib\sapnco_utils.dll 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | True 102 | Application.myapp 103 | 104 | 105 | True 106 | True 107 | Resources.resx 108 | 109 | 110 | True 111 | Settings.settings 112 | True 113 | 114 | 115 | 116 | 117 | 118 | 119 | VbMyResourcesResXFileCodeGenerator 120 | Resources.Designer.vb 121 | My.Resources 122 | Designer 123 | 124 | 125 | 126 | 127 | Designer 128 | 129 | 130 | app.config 131 | Designer 132 | 133 | 134 | MyApplicationCodeGenerator 135 | Application.Designer.vb 136 | 137 | 138 | SettingsSingleFileGenerator 139 | My 140 | Settings.Designer.vb 141 | 142 | 143 | 144 | 145 | {40dab722-d636-44c3-806e-2d9fd2515206} 146 | SAPExtractorDotNET 147 | 148 | 149 | 150 | 151 | 152 | 153 | False 154 | 155 | 156 | False 157 | 158 | 159 | False 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | $(TargetFileName).config 176 | 177 | 178 | 179 | 186 | -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/TableExtraction.vb: -------------------------------------------------------------------------------- 1 | Imports System.Text 2 | Imports Microsoft.VisualStudio.TestTools.UnitTesting 3 | Imports SAP.Middleware.Connector 4 | Imports SAPExtractorDotNET 5 | Imports System.Globalization 6 | Imports SAPExtractorDotNETTest.Util 7 | 8 | 9 | Public Class TableExtraction 10 | 11 | Private Const TestTable As String = "T001" 12 | Private Const TestTableWide As String = "MARA" 13 | Private Const TestDestination As String = "SILENT_LOGIN" 14 | 15 | 16 | Public Sub FindTable() 17 | 18 | Dim connector As New SAPConnector(TestDestination) 19 | 20 | Try 21 | Dim connection As RfcDestination = connector.Login 22 | Dim tables As List(Of SAPTableExtractor) = SAPTableExtractor.Find(connection, "DD*") 23 | 24 | For i As Integer = 0 To If(tables.Count > 10, 10, tables.Count) - 1 25 | Dim t = tables(i) 26 | Console.WriteLine(t.Table + ":" + t.TableText) 27 | Next 28 | 29 | Catch ex As Exception 30 | Console.WriteLine(ex.Message) 31 | Assert.Fail() 32 | End Try 33 | 34 | End Sub 35 | 36 | 37 | Public Sub GetColumnDefine() 38 | Dim connector As New SAPConnector(TestDestination) 39 | 40 | Try 41 | Dim connection As RfcDestination = connector.Login 42 | 43 | Dim tableExtractor As New SAPTableExtractor(TestTable) 44 | Dim columns As List(Of SAPFieldItem) = tableExtractor.GetColumnFields(connection) 45 | 46 | ResultWriter.Write(columns) 47 | 48 | Catch ex As Exception 49 | Console.WriteLine(ex.Message) 50 | Assert.Fail() 51 | End Try 52 | 53 | End Sub 54 | 55 | 56 | Public Sub ExtractTable() 57 | 58 | Dim connector As New SAPConnector(TestDestination) 59 | 60 | Try 61 | Dim connection As RfcDestination = connector.Login 62 | 63 | Dim tableExtractor As New SAPTableExtractor(TestTable) 64 | Dim table As DataTable = tableExtractor.Invoke(connection) 65 | ResultWriter.Write(table) 66 | 67 | Catch ex As Exception 68 | Console.WriteLine(ex.Message) 69 | Assert.Fail() 70 | End Try 71 | 72 | End Sub 73 | 74 | 75 | Public Sub ExtractTableWithFields() 76 | 77 | Dim connector As New SAPConnector(TestDestination) 78 | 79 | Try 80 | Dim connection As RfcDestination = connector.Login 81 | 82 | Dim tableExtractor As New SAPTableExtractor(TestTable) 83 | Dim table As DataTable = tableExtractor.Invoke(connection, {"BUKRS", "BUTXT"}, New SAPFieldItem("SPRAS").IsEqualTo("EN")) 84 | ResultWriter.Write(table) 85 | 86 | Catch ex As Exception 87 | Console.WriteLine(ex.Message) 88 | Assert.Fail() 89 | End Try 90 | 91 | End Sub 92 | 93 | 94 | 95 | Public Sub ExtractTableWithCriteria() 96 | 97 | Dim connector As New SAPConnector(TestDestination) 98 | 99 | Try 100 | Dim connection As RfcDestination = connector.Login 101 | 102 | Dim tableExtractor As New SAPTableExtractor(TestTableWide) 103 | Dim options As New List(Of SAPFieldItem) 104 | 105 | options.Add(New SAPFieldItem("MATNR").StartsWith("A")) 106 | 107 | Dim table As DataTable = tableExtractor.Invoke(connection, Nothing, options) 108 | ResultWriter.Write(table) 109 | 110 | Catch ex As Exception 111 | Console.WriteLine(ex.Message) 112 | Assert.Fail() 113 | End Try 114 | 115 | End Sub 116 | 117 | 118 | End Class -------------------------------------------------------------------------------- /SAPExtractorDotNETTest/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 |
9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /documents/SAPExtractorDotNETAPI.shfbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 7 | Debug 8 | AnyCPU 9 | 2.0 10 | {36ebc5c8-d578-4de7-921a-5278c806f0f3} 11 | 1.9.5.0 12 | 14 | Documentation 15 | Documentation 16 | Documentation 17 | 18 | .NET Framework 4.5 19 | .\Help\ 20 | SAPExtractorDotNETAPI 21 | en-US 22 | OnlyWarningsAndErrors 23 | HtmlHelp1, Website 24 | False 25 | True 26 | False 27 | False 28 | True 29 | 30 | 31 | 32 | 33 | Standard 34 | Blank 35 | False 36 | VS2010 37 | False 38 | Guid 39 | SAPExtractorDotNET 40 | AboveNamespaces 41 | SAP Query/Table Extractor 42 | 43 | SAP Query/Table Extractor 44 | 45 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /saploader/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 |
9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /saploader/MainModule.vb: -------------------------------------------------------------------------------- 1 | Imports SAPExtractorDotNET 2 | Imports SAP.Middleware.Connector 3 | Imports System.IO 4 | 5 | Module MainModule 6 | 7 | Sub Main(args As String()) 8 | 9 | Dim destination As String = "" 10 | Dim target As String = "" 11 | Dim filename As String = "" 12 | Dim isTable As Boolean = True 13 | 14 | If args.Length < 3 Then 15 | Console.WriteLine("You have to set obligate parameters (destination,target,filename)" + vbCrLf) 16 | showUsage() 17 | Else 18 | destination = args(0) 19 | target = args(1) 20 | filename = args(2) 21 | End If 22 | 23 | If IndexOfOption(args, "/Q") > -1 Then isTable = False 24 | 25 | 26 | Try 27 | 28 | 'create connector to SAP 29 | Dim connector As New SAPConnector(destination) 30 | 31 | 'get common options 32 | Dim options As List(Of SAPFieldItem) = makeOptions(args) 33 | Dim result As DataTable = Nothing 34 | 35 | Dim connection As RfcDestination = connector.Login 36 | Console.WriteLine("Connect to SAP " + connector.Destination) 37 | 38 | 'extract from SAP 39 | If isTable Then 40 | 'extract from table 41 | 42 | Dim fields As List(Of SAPFieldItem) = makeFields(args) 43 | Dim tableLoader As New SAPTableExtractor(target) 44 | result = tableLoader.Invoke(connection, fields, options) 45 | Console.WriteLine("Extraction done from " + tableLoader.Table) 46 | 47 | Else 48 | 'extract from query 49 | Dim queryInfos As String() = target.Split("/") 50 | If queryInfos.Count = 2 Then 51 | Dim queryName As String = queryInfos(0) 52 | Dim userGroup As String = queryInfos(1) 53 | Dim queryLoader As New SAPQueryExtractor(queryName, userGroup) 54 | queryLoader.QueryVariant = GetOptionValue(args, "/V") 55 | result = queryLoader.Invoke(connection, options) 56 | Console.WriteLine("Extraction done from " + queryLoader.Query + "/" + queryLoader.UserGroup) 57 | 58 | Else 59 | Throw New Exception("You have to set query by queryName/userGroup") 60 | End If 61 | 62 | 63 | End If 64 | 65 | 'write to file 66 | Dim writer As New StreamWriter(filename, False) 67 | Dim line As New List(Of String) 68 | If IndexOfOption(args, "/H") > -1 Or IndexOfOption(args, "/HC") > -1 Then 69 | For Each column As DataColumn In result.Columns 70 | If IndexOfOption(args, "/H") > -1 Then 71 | line.Add(column.ColumnName) 72 | Else 73 | line.Add(column.Caption) 74 | End If 75 | Next 76 | writer.WriteLine(String.Join(vbTab, line)) 77 | End If 78 | 79 | For Each row As DataRow In result.Rows 80 | line.Clear() 81 | For Each column As DataColumn In result.Columns 82 | line.Add(row(column.ColumnName)) 83 | Next 84 | writer.WriteLine(String.Join(vbTab, line)) 85 | Next 86 | 87 | writer.Close() 88 | 89 | Catch ex As Exception 90 | Console.WriteLine(ex.Message) 91 | End Try 92 | 93 | End Sub 94 | 95 | Private Function makeFields(ByVal arguments As String()) As List(Of SAPFieldItem) 96 | Const FieldOption As String = "/F" 97 | Dim fields As New List(Of SAPFieldItem) 98 | Dim parameterForField As String = GetOptionValue(arguments, FieldOption) 99 | 100 | If parameterForField IsNot Nothing Then 101 | Dim columns As String() = parameterForField.Split(",") 102 | 103 | For Each column As String In columns 104 | fields.Add(New SAPFieldItem(column)) 105 | Next 106 | 107 | End If 108 | 109 | Return fields 110 | 111 | End Function 112 | 113 | Private Function makeOptions(ByVal arguments As String()) As List(Of SAPFieldItem) 114 | Const OptionOption As String = "/O" 115 | Dim options As New List(Of SAPFieldItem) 116 | Dim parameterForOption As String = GetOptionValue(arguments, OptionOption) 117 | 118 | If parameterForOption IsNot Nothing Then 119 | Dim statements As String() = parameterForOption.Split(",") 120 | For i As Integer = 0 To statements.Count - 1 121 | 'greater part of query fields are select-option 122 | Dim f As SAPFieldItem = SAPFieldItem.createByStatement(statements(i), True) 123 | options.Add(f) 124 | Next 125 | End If 126 | 127 | Return options 128 | 129 | End Function 130 | 131 | Private Function GetOptionValue(ByVal arguments As String(), ByVal optionName As String) As String 132 | Dim optIndex As Integer = IndexOfOption(arguments, optionName) 133 | If optIndex > -1 Then 134 | If optIndex + 1 < arguments.Length Then 135 | Return arguments(optIndex + 1) 136 | Else 137 | Return Nothing 138 | End If 139 | Else 140 | Return Nothing 141 | End If 142 | 143 | End Function 144 | 145 | Private Function IndexOfOption(ByVal arguments As String(), ByVal optionName As String) As Integer 146 | Dim optIndex As Integer = -1 147 | For i As Integer = 0 To arguments.Count - 1 148 | If arguments(i).ToUpper = optionName.ToUpper Then 149 | optIndex = i 150 | Exit For 151 | End If 152 | Next 153 | 154 | Return optIndex 155 | End Function 156 | 157 | Sub showUsage() 158 | Dim usages As New List(Of String) 159 | usages.Add("saploader v" + Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString) 160 | usages.Add("usage:") 161 | usages.Add(" from table : saploader [/f ] [/o ]") 162 | usages.Add(" from query : saploader /q [/o ] [/v ]") 163 | usages.Add(" if you want to set condition or order to query, create query variant in SAP at present.") 164 | usages.Add(" other options: ") 165 | usages.Add(" /h : write header") 166 | usages.Add(" /hc : write header by caption text") 167 | usages.Add("examples:") 168 | usages.Add(" saploader MY_SAP T001 table.txt /t /f BUKRS,BUTXT /o BUKRS=1*") 169 | usages.Add(" saploader MY_SAP ZQUERY01/MYGROUP query.txt /q /v MY_VARIANT") 170 | usages.ForEach(Sub(u) Console.WriteLine(u)) 171 | 172 | End Sub 173 | 174 | End Module 175 | -------------------------------------------------------------------------------- /saploader/My Project/Application.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | -------------------------------------------------------------------------------- /saploader/My Project/Application.myapp: -------------------------------------------------------------------------------- 1 |  2 | 3 | false 4 | false 5 | 0 6 | true 7 | 0 8 | 2 9 | true 10 | 11 | -------------------------------------------------------------------------------- /saploader/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Reflection 3 | Imports System.Runtime.InteropServices 4 | 5 | ' アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 6 | ' アセンブリに関連付けられている情報を変更するには、 7 | ' これらの属性値を変更してください。 8 | 9 | ' アセンブリ属性の値を確認します。 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 'このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります。 21 | 22 | 23 | ' アセンブリのバージョン情報は、以下の 4 つの値で構成されています: 24 | ' 25 | ' Major Version 26 | ' Minor Version 27 | ' Build Number 28 | ' Revision 29 | ' 30 | ' すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を 31 | ' 既定値にすることができます: 32 | ' 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /saploader/My Project/Resources.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | Imports System 15 | 16 | Namespace My.Resources 17 | 18 | 'このクラスは StronglyTypedResourceBuilder クラスが ResGen 19 | 'または Visual Studio のようなツールを使用して自動生成されました。 20 | 'メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に 21 | 'ResGen を実行し直すか、または VS プロジェクトをビルドし直します。 22 | ''' 23 | ''' ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。 24 | ''' 25 | _ 29 | Friend Module Resources 30 | 31 | Private resourceMan As Global.System.Resources.ResourceManager 32 | 33 | Private resourceCulture As Global.System.Globalization.CultureInfo 34 | 35 | ''' 36 | ''' このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。 37 | ''' 38 | _ 39 | Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager 40 | Get 41 | If Object.ReferenceEquals(resourceMan, Nothing) Then 42 | Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("saploader.Resources", GetType(Resources).Assembly) 43 | resourceMan = temp 44 | End If 45 | Return resourceMan 46 | End Get 47 | End Property 48 | 49 | ''' 50 | ''' 厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、 51 | ''' 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。 52 | ''' 53 | _ 54 | Friend Property Culture() As Global.System.Globalization.CultureInfo 55 | Get 56 | Return resourceCulture 57 | End Get 58 | Set 59 | resourceCulture = value 60 | End Set 61 | End Property 62 | End Module 63 | End Namespace 64 | -------------------------------------------------------------------------------- /saploader/My Project/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /saploader/My Project/Settings.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' このコードはツールによって生成されました。 4 | ' ランタイム バージョン:4.0.30319.34209 5 | ' 6 | ' このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 7 | ' コードが再生成されるときに損失したりします。 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | Namespace My 16 | 17 | _ 20 | Partial Friend NotInheritable Class MySettings 21 | Inherits Global.System.Configuration.ApplicationSettingsBase 22 | 23 | Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) 24 | 25 | #Region "My.Settings 自動保存機能" 26 | #If _MyType = "WindowsForms" Then 27 | Private Shared addedHandler As Boolean 28 | 29 | Private Shared addedHandlerLockObject As New Object 30 | 31 | _ 32 | Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) 33 | If My.Application.SaveMySettingsOnExit Then 34 | My.Settings.Save() 35 | End If 36 | End Sub 37 | #End If 38 | #End Region 39 | 40 | Public Shared ReadOnly Property [Default]() As MySettings 41 | Get 42 | 43 | #If _MyType = "WindowsForms" Then 44 | If Not addedHandler Then 45 | SyncLock addedHandlerLockObject 46 | If Not addedHandler Then 47 | AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings 48 | addedHandler = True 49 | End If 50 | End SyncLock 51 | End If 52 | #End If 53 | Return defaultInstance 54 | End Get 55 | End Property 56 | End Class 57 | End Namespace 58 | 59 | Namespace My 60 | 61 | _ 64 | Friend Module MySettingsProperty 65 | 66 | _ 67 | Friend ReadOnly Property Settings() As Global.saploader.My.MySettings 68 | Get 69 | Return Global.saploader.My.MySettings.Default 70 | End Get 71 | End Property 72 | End Module 73 | End Namespace 74 | -------------------------------------------------------------------------------- /saploader/My Project/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /saploader/README.md: -------------------------------------------------------------------------------- 1 | saploader 2 | ============= 3 | 4 | This is command line application to extract data from SAP system. 5 | 6 | ## How to use 7 | from table 8 | 9 | ``` 10 | saploader [/c ] [/f ] [/o ] 11 | ``` 12 | 13 | from query 14 | 15 | ``` 16 | saploader /q [/o ] [/v ] 17 | ``` 18 | 19 | options 20 | 21 | ``` 22 | /h : write header 23 | /hc : write header by caption text 24 | ``` 25 | 26 | ## Set up 27 | To start `saploader` quickly,download quickstart/saploader.zip and expand it. 28 | And adjust `ClientSettings` in `saploader.exe.config` to connect your SAP. 29 | 30 | ## Examples 31 | 32 | ``` 33 | saploader MY_SAP T001 table.txt /t /f BUKRS,BUTXT /o BUKRS=1* 34 | saploader MY_SAP ZQUERY01/MYGROUP query.txt /q /v MY_VARIANT 35 | ``` 36 | -------------------------------------------------------------------------------- /saploader/quickstart/saploader.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icoxfog417/SAPExtractorDotNET/866fc823c97c4141a666279eb0a3667eb94c1b76/saploader/quickstart/saploader.zip -------------------------------------------------------------------------------- /saploader/saploader.vbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {97B833F9-0624-4F7F-A782-F5F373107193} 8 | Exe 9 | saploader.MainModule 10 | saploader 11 | saploader 12 | 512 13 | Console 14 | v4.0 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | true 22 | true 23 | bin\Debug\ 24 | saploader.xml 25 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | false 31 | true 32 | true 33 | bin\Release\ 34 | saploader.xml 35 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 36 | 37 | 38 | On 39 | 40 | 41 | Binary 42 | 43 | 44 | Off 45 | 46 | 47 | On 48 | 49 | 50 | 51 | ..\SAPExtractorDotNET\lib\rscp4n.dll 52 | 53 | 54 | ..\SAPExtractorDotNET\lib\sapnco.dll 55 | 56 | 57 | ..\SAPExtractorDotNET\lib\sapnco_utils.dll 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | True 83 | Application.myapp 84 | 85 | 86 | True 87 | True 88 | Resources.resx 89 | 90 | 91 | True 92 | Settings.settings 93 | True 94 | 95 | 96 | 97 | 98 | VbMyResourcesResXFileCodeGenerator 99 | Resources.Designer.vb 100 | My.Resources 101 | Designer 102 | 103 | 104 | 105 | 106 | MyApplicationCodeGenerator 107 | Application.Designer.vb 108 | 109 | 110 | SettingsSingleFileGenerator 111 | My 112 | Settings.Designer.vb 113 | 114 | 115 | 116 | 117 | 118 | {40dab722-d636-44c3-806e-2d9fd2515206} 119 | SAPExtractorDotNET 120 | 121 | 122 | 123 | 130 | --------------------------------------------------------------------------------