Crear Modelo de Costos Easy Cost Planning

11
 SAP ECC 6.03 Marzo de 2015 Español Crear modelo de cálculo de costos SAP AG Dietmar-Hopp-Al lee 16 610 !alldor " Germa#$ Pro%edimie#to de datos maestros

description

Crear Modelo de Costos Easy Cost Planning

Transcript of Crear Modelo de Costos Easy Cost Planning

Business Process Procedures

SAP ECC 6.03 Marzo de 2015EnglishEspaol

APOCrear modelo de clculo de costos

SAP AGDietmar-Hopp-Allee 1669190 WalldorfGermanyProcedimiento de datos maestros

Contenido31Propsito

32Requisitos

33Escenario

33.1Crear modelo - Submodelo

Crear clases y caractersticas1 PropsitoEl propsito de este documento es ilustrar la forma en que se deben crear los modelos de planificacin de costos en el sistema.2 RequisitosSe deben haber creado las caractersticas relevantes para cada modelo en el sistema.

3 Escenario3.1 Crear modelo Submodelo1. Acceda a la transaccin mediante una de las siguientes opciones de navegacin:

Opcin 1: interfaz grfica de usuario SAP (SAP GUI)Men SAPLogstica ( Sistema de proyectos( Datos bsicos ( modelos ( Modelos para Easy Cost Planning

Cdigo de transaccinCKCM

2. En la pantalla Easy Cost Planning: Modelo, realice lo siguiente:

3. En la ventana desplegada por el sistema ingrese el cdigo y la denominacin del modelo y pulse enter

4. En el rea de trabajo mostrada, ingrese los cdigos de las caractersticas relevantes para el modelo.

5. Para completar el modelo haga clic en Defina las normas de derivacin del modelo

6. En la ventana desplegada por el sistema seleccione 6 - Elemento PEP y haga clic en aceptar o presione enter.

7. En la ventana Crear modelo 205 / (CODIGO) Defina el modelo , de acuerdo con las siguientes consideraciones:

8. En la fila correspondiente de la columna Tipo, seleccione Material.9. Haga clic en la celda correspondiente de la columna objeto . El sistema deslpiega la siguiente ventana. Ingrese alli el codigo del material y el centro y haga clic en aceptar.

10. Haga clic c en la celda correspondiente de la columna cantidad . El sistema deslpiega un editor de formulas, que permitir modelar la lista de materiales.

En este caso, la cantidad total de la linea es una funcin de la cantidad de edificios y se parte de un valor base de 3.

Si se requieren 2 edificios, el sistema realizar el calculo como 3 * 2 = 6

Una vez finalice de editar la formula , haga clic en cantidad

11. Finalmente en la celda correspondiente a la columna activacin , indique que el objeto est activo.

12. Proceda de forma similar hasta incorporar todos los cdigos de material requeridos.13. Guarde las entradas ResultadoSe ha creado en el sistema un modelo de planificacin de costos.3.2 Crear modelo Modelo agrupado1. Acceda a la transaccin mediante una de las siguientes opciones de navegacin:

Opcin 1: interfaz grfica de usuario SAP (SAP GUI)Men SAPLogstica ( Sistema de proyectos( Datos bsicos ( modelos ( Modelos para Easy Cost Planning

Cdigo de transaccinCKCM

2. En la pantalla Easy Cost Planning: Modelo, realice lo siguiente:

3. En la ventana desplegada por el sistema ingrese el cdigo y la denominacin del modelo y pulse enter

4. En el rea de trabajo mostrada, ingrese los cdigos de las caractersticas relevantes para el modelo.

Esto debe realizarse si el valor de las caractersticas debe transferirse de desde el modelo principal a los submodelos. Si no es necesario, se puede omitir este paso.

5. Para completar el modelo haga clic en Defina las normas de derivacin del modelo

6. En la ventana desplegada por el sistema seleccione 6 - Elemento PEP y haga clic en aceptar o presione enter.

7. En la ventana Crear modelo 205 / (CODIGO) Defina el modelo , de acuerdo con las siguientes consideraciones:

8. En la fila correspondiente de la columna Tipo, seleccione Material.9. Haga clic en la celda correspondiente de la columna objeto . El sistema deslpiega la siguiente ventana. Ingrese alli el codigo del material y el centro y haga clic en aceptar.

10. Haga clic c en la celda correspondiente de la columna cantidad . El sistema deslpiega un editor de formulas, que permitir modelar la lista de materiales.

En este caso, la cantidad total de la linea es una funcin de la cantidad de edificios y se parte de un valor base de 3.

Si se requieren 2 edificios, el sistema realizar el calculo como 3 * 2 = 6

Una vez finalice de editar la formula , haga clic en cantidad

11. Finalmente en la celda correspondiente a la columna activacin , indique que el objeto est activo.

12. Proceda de forma similar hasta incorporar todos los cdigos de material requeridos.13. Guarde las entradas Resultado

Se ha creado en el sistema un modelo de planificacin de costos. SAP AG

Pgina 8 de 11

_1118216528.bin

Attribute VB_Name = "basDDSupdate"Option Explicit

' DDS - Main update functions - Version v0.4a

' - modifiziert : DDS wird immer aktualisiert, solange PersAssi das UpdateDataSource Flag nicht setzt

'***********************************************'* *'* by Armin Laschet 01/2006 *'* for SAP Best Practices *'* [email protected] *'* *'***********************************************

Public mOpenedByDEV As Boolean

Function updateDataSource(ByVal openedByDEV As Boolean, ByVal envFileName As String, _ Optional ByVal variantsFolder As String = "", _ Optional ByVal documentationDataSourceFolder As String = "", _ Optional ByVal listTDCFolderPath As String = "") As BooleanDim dataFilesFolder As String, environmentFilePath As StringDim documentationFieldsListPath As String, documentationDataSourceFilePath As StringDim varDDS As Variant, answer As VbMsgBoxResult, envFileCont As Variant mOpenedByDEV = openedByDEV If Not mOpenedByDEV Then ' user/ customer 'get path to environment file - if file doesn't exist, exit createWB() environmentFilePath = getEnvironmentFilePath(envFileName) If environmentFilePath = "" Then MsgBox "Environment settings are not available - make sure" & vbCr & _ "to have carried out the definition of Enviroment Settings" & vbCr & _ "as first step of personalization", vbCritical, "No Settings" updateDataSource = False Exit Function End If ' Read content of environment file into array envFileCont = getFileContent2D(environmentFilePath) If Not IsArray(envFileCont) Then MsgBox "Environment settings are not available - make sure" & vbCr & _ "to have carried out the definition of Enviroment Settings" & vbCr & _ "as first step of personalization", vbCritical, "No Settings" updateDataSource = False Exit Function End If 'get path to data files (TDCs etc) from environment file dataFilesFolder = getDataFilesFolder(envFileCont) If Not PathFileExists(dataFilesFolder) Then MsgBox "The folder for the external variants" & vbCr & _ "could not be retrieved from the " & vbCr & _ "environment file." & vbCr & _ "Maybe the file is corrupt.", vbCritical, "File corrupt?" updateDataSource = False Exit Function Else dataFilesFolder = AppendBackSlash(dataFilesFolder) End If Else ' DEV dataFilesFolder = variantsFolder End If

' check, whether GC_FLN_DFL exists, where all fields are listed that are used by MailMerge ' in documentation documents (BPP, ConfigGuides) If Not mOpenedByDEV Then ' user/ customer documentationFieldsListPath = dataFilesFolder & GC_FLN_DFL Else ' DEV documentationFieldsListPath = documentationDataSourceFolder & GC_FLN_DFL End If

If Not PathFileExists(documentationFieldsListPath) Then MsgBox "Could not find" & vbCr & "'" & documentationFieldsListPath & "'.", _ vbCritical, "File unavailable" updateDataSource = False Exit Function End If

' load GC_FLN_DFL into (array) varDDS varDDS = getFileContent2D(documentationFieldsListPath, 1) If Not IsArray(varDDS) Then ' no access to DFL or DFL is empty MsgBox "Could not import Documentation Fields List.", vbCritical, "File unavailable" updateDataSource = False Exit Function End If If createDataSource(varDDS, dataFilesFolder, listTDCFolderPath) = False Then If mOpenedByDEV Then ' sth. went wrong: ' a TDC/Variant File could not be accessed or is empty ' a parameter or a variant could not be found in the respective TDC/Variant File ' errors are reported in function createDataSource() MsgBox "There were errors." & vbCr & _ "The '" & GC_FLN_DDS & "'" & vbCr & _ "will not be created/ updated.", vbCritical, "Error(s)" Exit Function Else ' for a user this means, that some fields in the document will not be updated End If End If ' export Data Source to .txt file If Not mOpenedByDEV Then ' for USER/DVD version variant files and DDS will be in variants folder documentationDataSourceFilePath = dataFilesFolder & GC_FLN_DDS Else ' DEV documentationDataSourceFilePath = documentationDataSourceFolder & GC_FLN_DDS End If ' only show message when this function was called by a developer If mOpenedByDEV Then ' DEV If PathFileExists(documentationDataSourceFilePath) Then answer = MsgBox("'" & GC_FLN_DDS & "' in" & vbCr & "'" & documentationDataSourceFolder & _ "'" & vbCr & "already exists." & vbCr & "Choose 'OK' to update existing file", vbOKCancel Or vbQuestion, "Overwrite File?") If answer = vbCancel Then MsgBox "The '" & GC_FLN_DDS & "'" & vbCr & _ "will not be created/ updated.", vbInformation, "Update Cancelled" updateDataSource = False Exit Function End If End If End If If FileExportArr(documentationDataSourceFilePath, varDDS) = False Then If mOpenedByDEV Then MsgBox "Could not create/ update" & vbCr & _ "'" & GC_FLN_DDS & "'." & vbCr & _ "Maybe the file is locked.", vbCritical, "Error" Else Debug.Print "Data Source File could not be accessed." End If updateDataSource = False Else ' user/customer: set flag in environment file (data source is now up to date) If Not mOpenedByDEV Then ' Old - modified: ' Solange der PersAssi das Flag fr UpdateDataSource auf true setzt, wird es hier immer auf true gesetzt 'If Not updateEnvironmentFile(environmentFilePath, envFileCont, GC_KEY_ENVFILE_UPDATE_DDS, GC_VAL_TRUE, True) Then ' mod: ohne Flag If Not updateEnvironmentFile(environmentFilePath, envFileCont, GC_KEY_ENVFILE_UPDATE_DDS, GC_VAL_FALSE, True) Then ' mit Flag ' File could not be accessed Debug.Print "Environment file could not be updated" End If End If updateDataSource = True End If End Function

Private Function createDataSource(ByRef varDDS As Variant, _ ByVal dataFilesFolder As String, _ Optional ByVal listTDCFolderPath As String = "") As BooleanDim lngRow As Long, lngLastRow As Long lngRow = 0 Do If lngRow > UBound(varDDS, 2) Then Exit Do End If lngLastRow = getLastRowForFile(varDDS, lngRow) If getValues(varDDS, lngRow, lngLastRow, dataFilesFolder, listTDCFolderPath) = False Then If mOpenedByDEV Then ' error reported in function getValues() createDataSource = False Exit Function End If End If lngRow = lngLastRow + 1 Loop createDataSource = True

End Function

Private Function getLastRowForFile(ByRef varDDS As Variant, _ ByVal startRow As Long) As LongDim lngRow As Long, fileName As String

fileName = Trim(varDDS(GC_COL_DDS_FILENAME, startRow)) getLastRowForFile = startRow For lngRow = startRow + 1 To UBound(varDDS, 2) If Trim(varDDS(GC_COL_DDS_FILENAME, lngRow)) = fileName Then getLastRowForFile = lngRow Else Exit For End If Next lngRow End Function

Private Function getValues(ByRef varDDS As Variant, _ ByVal startRow As Long, _ ByVal lastRow As Long, _ ByVal dataFilesFolder As String, _ Optional ByVal listTDCFolderPath As String = "") As BooleanDim filePath As String, varFileContent As Variant, lngRow As Long, paramCol As Integer, varRow As LongDim param As String, varnt As String, val As String

filePath = dataFilesFolder & Trim(varDDS(GC_COL_DDS_FILENAME, startRow)) & GC_FXT_DEF_TEXT varFileContent = getFileContent2Dunicode(filePath) If Not IsArray(varFileContent) Then If mOpenedByDEV Then MsgBox "Could not access" & vbCr & "'" & filePath & "'" & vbCr & _ "or file is empty.", vbCritical, "File Error" Else Debug.Print filePath & " can not be accessed or is empty." End If getValues = False Exit Function End If For lngRow = startRow To lastRow param = Trim(varDDS(GC_COL_DDS_PARAM, lngRow)) varnt = Trim(varDDS(GC_COL_DDS_VARIANT, lngRow)) paramCol = getParamCol(varFileContent, param) If paramCol = -1 Then ' param not found If mOpenedByDEV Then MsgBox "Could not find parameter '" & param & "'" & vbCr & _ "in '" & filePath & "'.", vbCritical, "Parameter not found" getValues = False Exit Function Else Debug.Print param & " is not in " & filePath GoTo nextRow End If End If varRow = getVariantRow(varFileContent, varnt) If varRow = -1 Then ' variant not found If mOpenedByDEV Then MsgBox "Could not find variant '" & varnt & "'" & vbCr & _ "in '" & filePath & "'.", vbCritical, "Variant not found" getValues = False Exit Function Else Debug.Print varnt & " is not in " & filePath GoTo nextRow End If End If val = varFileContent(paramCol, varRow) val = Replace(val, "#", "") ' remove '#', e.g. from "#01' ' Check, if val is a reference to a TDC. If so, get the TDC's param value If deRef_isReference(val) = True Then ' val is reference Dim reslt As Variant, tmpVal As String reslt = deRef_getValueOfParam(tmpVal, val, dataFilesFolder, False, listTDCFolderPath) If reslt = GC_RET_ALL_OK Then ' val was dereferenced, 'real' value is in tmpVal varDDS(GC_COL_DDS_VALUE, lngRow) = tmpVal Else ' Sth. went wrong - cannot dereference val ' for now, show old value -> do nothing Debug.Print "Error, while dereferencing '" & val & "'" Debug.Print "listTDCfolderPath: " & listTDCFolderPath End If Else varDDS(GC_COL_DDS_VALUE, lngRow) = val ' val is no reference -> use it End If nextRow: Next lngRow getValues = True End Function

Private Function getParamCol(ByRef varFileContent As Variant, ByVal param As String) As IntegerDim intCol As Integer

For intCol = LBound(varFileContent, 1) To UBound(varFileContent, 1) If UCase(Trim(varFileContent(intCol, GC_ROW_TDC_PARAMNAMES))) = UCase(param) Then ' found param getParamCol = intCol Exit Function End If Next intCol getParamCol = -1 ' indicates, that param could not be found

End Function

Private Function getVariantRow(ByRef varFileContent As Variant, ByVal varnt As String) As LongDim intRow As Long

For intRow = LBound(varFileContent, 2) To UBound(varFileContent, 2) If UCase(Trim(varFileContent(GC_COL_TDC_VARIANTID, intRow))) = UCase(varnt) Then ' found variant getVariantRow = intRow Exit Function End If Next intRow getVariantRow = -1 ' indicates, that param could not be found

End Function

Private Function getDataFilesFolder(ByVal envFileCont As Variant) As String' tries to read the path to the variant files from envFilePath (path to the environment file)Dim folderExternalVariants As String, strLine As String, row As Long

For row = LBound(envFileCont, 2) To UBound(envFileCont, 2) If Trim(envFileCont(0, row)) = GC_KEY_ENVFILE_TARGETFOLDER Then getDataFilesFolder = Trim(envFileCont(1, row)) Exit Function End If Next row End Function

Attribute VB_Name = "basDeRefMain"Option Explicit

' deREF - deReferencingTool - Main - Version v0.7d

'***********************************************'* *'* by Armin Laschet 03/2006 *'* for SAP Best Practices *'* [email protected] *'* *'***********************************************

' Notes:' - All arrays are 0-based (Option Base 0 = default)' - The content of a TDC file is read into an array.' The syntax to address a value is array(column,row).

'---------------------------GLOBAL CONSTANTS---------------------------------------

' Indices of the first dimension of the array, that contains all variant IDs, descriptions and values of a TDC filePublic Const VA_VAR_ID_IDX As Integer = 0 ' idx of variant ID - used in: basDeRefPersAssiPublic Const VA_DESCR_IDX As Integer = 1 ' idx of (variant) description - used in: basDeRefPersAssiPublic Const VA_VAL_IDX As Integer = 2 ' idx of value - used in: basDeRefPersAssi

'---------------------------LOCAL CONSTANTS (only basDeRefMain)----------------------------------------

' Array, that contains the content of List_TDC.txt (GC_FLN_LIST_TDC)' The array will be filled and returned by function getTDCasArray())Private globalListTDCarr As Variant

' Collection of imported TDCs (each TDC in the collection is a 0-based 2-dimensional array)Private globalTDCcoll As Collection

' Collection of the file paths of the imported TDCs, e.g. 'C:\Variants\SMB99_COMPANY_CODE_D06_J02.TXT'Private globalTDCpathsColl As Collection

'---------------------------LOCAL DECLARATIONS ---------------------------------------------------------

Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long

'-------------------------------------------------- MAIN FUNCTIONS --------------------------------------------------------------

Public Function deRef_isReference(ByVal term As String) As BooleanDim pos As Integer, posRev As Integer, i As IntegerDim requiredCharsArr As Variant, posArr() As Integer

' expects: any term as String' returns: true if term is an eCATT reference; false, if not

' A reference looks like' I_ACTION(DXX,VARIANT_1)' param TDC variant

' Conditions:' 1) ( , ) must appear in term just once' 2) ( , ) must appear in that order' 3) at least one char must be before (' 4) at least 3 chars must be between ( and ,' 5) at least 1 char must be between , and )' 6) there must not be any char after )

' 1) requiredCharsArr = Array("(", ",", ")") ReDim posArr(0 To 2) For i = LBound(requiredCharsArr) To UBound(requiredCharsArr) posArr(i) = InStr(1, term, requiredCharsArr(i)) If posArr(i) = 0 Then ' char is not in term deRef_isReference = False Exit Function End If posRev = InStrRev(term, requiredCharsArr(i)) If posArr(i) posRev Then ' char is more than once in term deRef_isReference = False Exit Function End If Next i ' 2) If Not (posArr(0) < posArr(1) And posArr(1) < posArr(2)) Then deRef_isReference = False Exit Function End If ' 3) If posArr(0) < 2 Then deRef_isReference = False Exit Function End If ' 4) If posArr(1) get its content tdcArr = getFileContent2D(tdcFilePath, extraColumns, delim, True) If IsArray(tdcArr) Then ' retrieved content of TDC ' Add TDC file path and array to collections globalTDCpathsColl.Add tdcFilePath globalTDCcoll.Add tdcArr getTDCasArray = tdcArr ' return TDC array ElseIf tdcArr = GC_RET_FILE_OPEN_ERROR Then getTDCasArray = GC_RET_TDC_OPEN_ERROR ElseIf tdcArr = GC_RET_FILE_EMPTY Then getTDCasArray = GC_RET_TDC_FILE_EMPTY Else getTDCasArray = False ' retain compatibility with regular version of getFileContent2D End If End Function

Function getListTDCasArray(ByVal listTDCFolderPath As String, _ Optional ByVal extraColumns As Integer = 0, _ Optional ByVal delim As String = vbTab, _ Optional ByVal trimParts As Boolean = False) As VariantDim listTDCpath As String

' expects:' - path to folder with List_TDC.txt (with or w/o trailing '\')' optional:' - number of (empty) columns to be added for later user (default: 0)' - delimiter for the entries in each row (default: tab)' - indicator, if leading/ trailing spaces of each entry in a row should be removed (default: false)' returns:' - success: the content of List_TDC.txt (GC_FLN_LIST_TDC)' as a 0-based 2-dimensional array.' - error: GC_RET_LIST_OPEN_ERROR- List_TDC.txt could not be accessed' GC_RET_FILE_EMPTY - List_TDC.txt is empty' 'False' (boolean) = TDC file could not be accessed/ is empty' Retain compatibility with original version of getFileContent2D,' which only returns false, when sth. went wrong

If IsArray(globalListTDCarr) Then ' List_TDC.txt has already been read into globalListTDCarr getListTDCasArray = globalListTDCarr Exit Function End If ' Read List_TDC.txt into globalListTDCarr ' append '\' if needed listTDCFolderPath = IIf(Right(listTDCFolderPath, 1) = "\", listTDCFolderPath, listTDCFolderPath & "\") listTDCpath = listTDCFolderPath & GC_FLN_LIST_TDC globalListTDCarr = getFileContent2D(listTDCpath, extraColumns, delim, trimParts) If IsArray(globalListTDCarr) Then ' all ok - return reference to globalListTDCarr getListTDCasArray = globalListTDCarr Exit Function ElseIf globalListTDCarr = GC_RET_FILE_OPEN_ERROR Then globalListTDCarr = GC_RET_LIST_OPEN_ERROR ElseIf globalListTDCarr = GC_RET_FILE_EMPTY Then globalListTDCarr = GC_RET_FILE_EMPTY Else globalListTDCarr = False ' retain compatibility with regular version of getFileContent2D End If getListTDCasArray = globalListTDCarr ' adopt (error) return value from getFileContent2D globalListTDCarr = "" ' reset globalListTDCarr End Function

Public Function getTdcFileName(ByVal listTDCFolderPath As String, _ ByVal ref As String, _ Optional ByVal checkRef As Boolean = False, _ Optional ByVal asUpperCase As Boolean = False) As StringDim inLine As String, parts() As String, tdcAlias As String, firstLine As Boolean, listTDCpath As StringDim listTDCarr As Variant, rw As Integer

' expects:' - path to folder with List_TDC.txt, e.g. 'C:\temp\' (with or without trailing '\')' - (valid) reference like I_ACTION(DXX,VARIANT_1)' optional:' - check, if ref is a valid reference' - return TDC filename as upper case' returns:' - success: the name of the respective TDC file, e.g. 'SMB99_PLANT_D14_J02.TXT'' - error: GC_RET_NO_REF = ref is not a valid reference' GC_RET_LIST_OPEN_ERROR = could not access List_TDC.txt' GC_RET_FILE_EMPTY = List_TDC.txt is empty' GC_RET_NOT_FOUND = could not find ref(TDCalias or file name) in listTDCpath

If checkRef Then If Not deRef_isReference(ref) Then getTdcFileName = GC_RET_NO_REF Exit Function End If End If listTDCarr = getListTDCasArray(listTDCFolderPath) If Not IsArray(listTDCarr) Then ' List_TDC.txt could not be accessed or is empty -> exit If listTDCarr = GC_RET_LIST_OPEN_ERROR Then getTdcFileName = GC_RET_LIST_OPEN_ERROR ElseIf listTDCarr = GC_RET_FILE_EMPTY Then getTdcFileName = GC_RET_FILE_EMPTY Else ' return value was 'false' - retain compatibility with regular getFileContent2D getTdcFileName = GC_RET_LIST_OPEN_ERROR End If Exit Function End If ' Find TDC in ListTDC array tdcAlias = Trim(Mid(ref, InStr(ref, "(") + 1, InStr(ref, ",") - InStr(ref, "(") - 1)) For rw = LBound(listTDCarr, 2) To UBound(listTDCarr, 2) If UCase(listTDCarr(GC_COL_LISTTDC_ALIAS, rw)) = UCase(tdcAlias) Then ' found TDC If UBound(listTDCarr, 1) >= 3 Then ' listTDCarr must have at least 4 'columns' getTdcFileName = listTDCarr(GC_COL_LISTTDC_FILENAME, rw) If asUpperCase Then getTdcFileName = UCase(getTdcFileName) End If Else ' file name is missing (too few columns in listTDCarr) getTdcFileName = GC_RET_NOT_FOUND End If Exit Function End If Next rw ' If we get here, TDC is not in List_TDC.txt getTdcFileName = GC_RET_NOT_FOUND End Function

Public Function getTDCalias(ByVal ref As String, _ Optional ByVal checkRef As Boolean = False, _ Optional ByVal asUpperCase As Boolean = False) As String ' expects: (valid) reference like I_ACTION(DXX,VARIANT_1)' optional:' - check, if ref is a valid reference' - return TDC alias as upper case' returns:' - success: TDC alias, e.g. 'DXX'' - error: GC_RET_NO_REF = ref is not a valid reference If checkRef Then If Not deRef_isReference(ref) Then getTDCalias = GC_RET_NO_REF Exit Function End If End If

getTDCalias = Trim(Mid(ref, InStr(ref, "(") + 1, InStr(ref, ",") - InStr(ref, "(") - 1)) If asUpperCase Then getTDCalias = UCase(getTDCalias) End If

End Function

' Checks, whether a filename is a TDC filenamePublic Function isTDCfilename(ByVal fileName As String) As StringDim parts() As String, tdcPart As String

' expects: filename, e.g. 'C:\tem\SMB99_PURCHASING_ORG_D12_J02.TXT'' returns:' - success: TDC Alias, e.g. 'D12'' - 'error': empty String ""

' Remove file extension fileName = Replace(UCase(fileName), UCase(GC_FXT_DEF_TEXT), "", 1, 1) ' Split filename into parts parts = Split(fileName, "_") ' There must be at least 4 parts, e.g. "SMB99_ANYTHING_D88_J01" If UBound(parts) < 3 Then isTDCfilename = "" Exit Function End If ' Check, if the last part indicates a version, e.g. "SMB99_ANYTHING_D88_J01_01" If Len(parts(UBound(parts))) = 2 Then ' version If UBound(parts) < 4 Then ' if filename has version appended, there must be at least 5 parts isTDCfilename = "" Exit Function End If tdcPart = parts(UBound(parts) - 2) ' use last but two part ElseIf Len(parts(UBound(parts))) = 3 Then ' no version tdcPart = parts(UBound(parts) - 1) ' use last but one part Else ' illegal ending isTDCfilename = "" Exit Function End If ' Check, if tdcPart is indicating a TDC If Len(tdcPart) 3 Then ' length must be 3 isTDCfilename = "" Exit Function End If If Not Left(tdcPart, 1) = "D" Then ' tdcPart must start with 'D' isTDCfilename = "" Exit Function End If ' fileName is a TDCfilename (at least: it might be ...) isTDCfilename = tdcPart

End Function

Public Function getParam(ByVal ref As String, _ Optional ByVal checkRef As Boolean = False, _ Optional ByVal asUpperCase As Boolean = False) As String ' expects: (valid) reference like I_ACTION(DXX,VARIANT_1)' optional:' - check, if ref is a valid reference' - return param as upper case' returns:' - success: parameter, e.g. 'I_ACTION'' - error: GC_RET_NO_REF = ref is not a valid reference

If checkRef Then If Not deRef_isReference(ref) Then getParam = GC_RET_NO_REF Exit Function End If End If

getParam = Trim(Mid(ref, 1, InStr(ref, "(") - 1)) If asUpperCase Then getParam = UCase(getParam) End If

End Function

Public Function getVariant(ByVal ref As String, _ Optional ByVal checkRef As Boolean = False, _ Optional ByVal asUpperCase As Boolean = False) As String ' expects: (valid) reference like I_ACTION(DXX,VARIANT_1)' optional:' - check, if ref is a valid reference' - return variant as upper case' returns:' - success: variant, e.g. 'VARIANT_1'' - error: GC_RET_NO_REF = ref is not a valid reference

If checkRef Then If Not deRef_isReference(ref) Then getVariant = GC_RET_NO_REF Exit Function End If End If getVariant = Trim(Mid(ref, InStr(ref, ",") + 1, Len(ref) - InStr(ref, ",") - 1)) If asUpperCase Then getVariant = UCase(getVariant) End If End Function

Function getParamCol(ByVal param As String, _ ByRef tdcArr As Variant) As IntegerDim row As Long, col As Integer

' expects: parameter name and TDC file content as array' returns: column of param(eter name) (-1, if param is not found)

row = GC_ROW_TDC_PARAMNAMES For col = LBound(tdcArr, 1) To UBound(tdcArr, 1) If LCase(tdcArr(col, row)) = LCase(param) Then ' found param getParamCol = col Exit Function End If Next col getParamCol = -1 ' param not found End Function

Function getVariantRow(ByVal var As String, _ ByRef tdcArr As Variant) As LongDim row As Long, col As Integer

' expects: variant name and TDC file content as array' returns: row of var(iant) (-1, if var is not found) col = GC_COL_TDC_VARIANTID For row = LBound(tdcArr, 2) To UBound(tdcArr, 2) If LCase(tdcArr(col, row)) = LCase(var) Then ' found var getVariantRow = row Exit Function End If Next row getVariantRow = -1 ' var not found End Function

' Creates and saves a list with all eCATT Test Data Containers in a given folderFunction createListTDCfile(ByVal varFilesFolder As String, _ Optional ByVal listTDCoutputFolder As String = "") As BooleanDim fileName As String, tdcFiles() As String, idx As Integer, tdcAlias As StringDim listTdcFilePath As String

' expects:' - path to the folder with the TDCs and the Variant Files' optional:' - path to the folder, the List_TDC.txt will be saved to' returns : true, if TDCs were found and List_TDC.txt was saved' false, if no TDCs were found or List_TDC.txt could not be saved

' Find all files in varFilesFolder ' - that start with 'SMB', followed by two characters and an underscore ' - that contain _DXX_, where 'XX' are any two characters ' - with default text file extension fileName = Dir(varFilesFolder & "\SMB??_*_D??_*" & GC_FXT_DEF_TEXT)

ReDim tdcFiles(0 To 1, 0 To 0) idx = 0 Do While fileName vbNullString ' As long as there are filenames found, go on tdcAlias = isTDCfilename(fileName) If tdcAlias "" Then ReDim Preserve tdcFiles(0 To 1, 0 To idx) tdcFiles(GC_COL_LISTTDC_ALIAS, idx) = tdcAlias tdcFiles(GC_COL_LISTTDC_FILENAME, idx) = fileName idx = idx + 1 End If ' Get the next file, if any fileName = Dir() Loop

If idx = 0 Then ' no files found createListTDCfile = False Exit Function End If If listTDCoutputFolder = "" Then ' use default -> users's temp folder Const kLength = 255& Dim nBuffer As String listTDCoutputFolder = GetTempPath(kLength, nBuffer) & "\" Else ' append '\' if needed listTDCoutputFolder = IIf(Right(listTDCoutputFolder, 1) = "\", listTDCoutputFolder, listTDCoutputFolder & "\") End If ' Save List_TDC.txt listTdcFilePath = listTDCoutputFolder & GC_FLN_LIST_TDC If FileExportArr(listTdcFilePath, tdcFiles) = False Then ' could not acess listTdcFilePath createListTDCfile = False Else createListTDCfile = True End If

End Function

Attribute VB_Name = "basGeneralConstants"Option Explicit

' GC - General Constants - v0.1b

'***********************************************'* *'* by Armin Laschet 03/2006 *'* for SAP Best Practices *'* [email protected] *'* *'***********************************************

' Acronyms:

' DAA - Documentation Adaptation Assistant' DAW - Documentation Adaptation Wizard' DDS - Documentation Data Source' DFA - Documentation Fields Assistant' DFL - Documentation Fields List' DUW - Documentation Upgrade Wizard

' Naming Convention:

' GC = Global Constants

' FLN = File Name' FOL = Folder name' PTH = Path (to folder/ file)' KEY = Key in a file (Header/ Entry)' VAL = Value in a file (corresponds to KEY)' FXT = file extension' APP = Application name = Word document or Excel workbook with Macros' ROW = Row (in a text file)' COL = Column (in a text file)' RET = Return value' DIV = Other values

' Examples:

' GC_FLN_DDS = File name of the Documentation Data Source' GC_KEY_TMP_TARGETFOLDER = key of an entry in a temporary file (e.g. SAP_Best_Practices_Project_Info.txt)

' -------------------------------------------------File and Folder Names/ Paths-----------------------------------------

Public Const GC_APP_DFA As String = "DocumentationFieldsAssistant.xls" ' Name of the DFA workbook

Public Const GC_FLN_DDS As String = "DocumentationDataSource.txt" ' Name of the file, that serves as the data source for the Automated Adaptation of Documentation

Public Const GC_FLN_DDS_DEF As String = "DocumentationDataSource_DEFAULT.txt" ' Name of the file, that serves as the default data source for the Automated Adaptation of Documentation

Public Const GC_FLN_DFL As String = "DocumentationFieldsList.txt" ' Name of the file with the field names used by the Automated Adaptation of Documentation

Public Const GC_FLN_DFL_DEF As String = "DEFAULT_DocumentationFieldsList.txt" ' Name of the file with the default field names used by the Automated Adaptation of Documentation

Public Const GC_FLN_LIST_TDC As String = "List_TDC.txt" ' Name of the file with TDC filenames and their aliases

Public Const GC_FLN_TMP_BPP_DEV As String = "SAP_Best_Practices_Project_Info_DEV.txt" ' Settings file, created by BPP Development Modules/ Macros

Public Const GC_FLN_TMP_DAW As String = "SAP_BP_DAW_Info.txt" ' Settings file, created by DAW

Public Const GC_FLN_TMP_ENVIRONMENTFILE As String = "SAP_Best_Practices_Project_Info.txt" ' Environment file created by Personlization Assistant

Public Const GC_FLN_TMP_SPAN As String = "SAPBP_SPAN_Settings.xml" ' Settings file, created by SPAN (Simple Project Administration Environment)

Public Const GC_FOL_DFL_DEF As String = "DefaultList" ' Name of the folder with the GC_FLN_DFL_DEF (Default Documentation Fields List)

Public Const GC_FOL_DAW_PLUGINS As String = "PlugIns" ' Name of the folder with the plugins for DAW

Public Const GC_PTH_LIST_TDC_FOLDER As String = "\\dwdf030\sme\Variants\SpecialFunctions\FlexibleDocumentation\deREF_tmp" ' Name of the folder with the GC_FLN_LIST_TDC (List_TDC.txt)

' -------------------------------------------------File Extensions-------------------------------------------------------

Public Const GC_FXT_DEF_TEXT As String = ".txt" ' Default file extension for text based files

' -------------------------------------------------Keys and Values in Text Files-----------------------------------------

Public Const GC_KEY_ENVFILE_TARGETFOLDER As String = "TargetFolder" ' Key in GC_FLN_TMP_ENVIRONMENTFILE (SAP_Best_Practices_Project_Info.txt/ SAP_Best_Practices_Project_Info_DEV.txt); indicates entry for user selection: location of target folder for environment creation

Public Const GC_KEY_ENVFILE_UPDATE_DDS As String = "UpdateDataSource" ' Key in GC_FLN_TMP_ENVIRONMENTFILE (SAP_Best_Practices_Project_Info.txt); indicates entry for tool flag: DDS has to be updated

Public Const GC_KEY_ENVFILE_USEPERSDATA As String = "UsePersDataInDocu" ' Key in GC_FLN_TMP_ENVIRONMENTFILE (SAP_Best_Practices_Project_Info.txt); indicates entry for user selection: Use personalized or default data in documents

Public Const GC_KEY_CTRLFILESFOLDER As String = "ControlFilesFolder" ' Key in settings file GC_FLN_TMP_DAW (SAP_BP_DAW_Info.txt); indicates entry for user selection: location of folder with control files

Public Const GC_KEY_DATAFILESFOLDER As String = "DataFilesFolder" ' Key in settings file GC_FLN_TMP_DAW (SAP_BP_DAW_Info.txt); indicates entry for user selection: location of folder with data files DDS and DFL Public Const GC_KEY_CTRL_FILENAME As String = "Filename" ' Key in Control Files; indicates the row in a control file, where the referenced variant file is listed

Public Const GC_VAL_TRUE As String = "True" ' Value in (Text-) Files; indicates, that the respective flag (key) is set to True (Boolean)

Public Const GC_VAL_FALSE As String = "False" ' Value in (Text-) Files; indicates, that the respective flag (key) is set to False (Boolean)

' -------------------------------------------------Special Rows and Columns in (Text-) Files-----------------------------

' -------TDC / Variant Files (Here, 'TDC' indicates TDC and ext. Variants File)-------

Public Const GC_ROW_TDC_PARAMNAMES As Integer = 0 ' Row with parameter names in a TDC/ ext. Variant File; 0 = row 1

Public Const GC_ROW_TDC_PARAMDESCR As Integer = 1 ' Row, with the parameter descriptions in a TDC/ ext. Variant File; 1 = row 2

Public Const GC_ROW_TDC_PARAMDEFAULTS As Integer = 2 ' Row, with the parameter descriptions in a TDC/ ext. Variant File; 2 = row 3

Public Const GC_ROW_TDC_VARIANTSTART As Integer = 3 ' Row, where listing of the variants starts in a TDC/ ext. Variant File; 3 = row 4

Public Const GC_COL_TDC_VARIANTID As Integer = 0 ' Column with Variant IDs in a TDC/ ext. Variant File; 0 = column 1

Public Const GC_COL_TDC_VARIANTDESCR As Integer = 1 ' Column with Variant descriptions in a TDC/ ext. Variant File; 1 = column 2

' -----------------------------------List_TDC.txt-------------------------------

Public Const GC_COL_LISTTDC_ALIAS As Integer = 0 ' Column with TDC aliases in List_TDC.txt; 0 = column 1

Public Const GC_COL_LISTTDC_FILENAME As Integer = 1 ' Column with TDC filename in List_TDC.txt; 3 = column 4

' ------------------------DDS (DocumentationDataSource.txt)-----------------------

' Columns

Public Const GC_COL_DDS_FILENAME As Integer = 0 ' File name of TDC/ Variant File

Public Const GC_COL_DDS_VARIANT As Integer = 1 ' Variant ID

Public Const GC_COL_DDS_PARAM As Integer = 2 ' Parameter name

Public Const GC_COL_DDS_FLDNAME As Integer = 3 ' Field name in Documents (e.g. BPPs)

Public Const GC_COL_DDS_VALUE As Integer = 4 ' Current Value

Public Const GC_COL_DDS_LASTCOL As Integer = 4 ' Index of last column

' -------------------------------------------------Return Constants-----------------------------------------------------

Public Const GC_RET_NO_REF As String = "c3jIl9dop9" ' Term is no reference

Public Const GC_RET_FILE_OPEN_ERROR As String = "jZ7cPw0mwP" ' Could not access file

Public Const GC_RET_TDC_OPEN_ERROR As String = "b71Jsx0LSq" ' Could not access TDC

Public Const GC_RET_LIST_OPEN_ERROR As String = "1lxuI6cYp2" ' Could not access List_TDC.txt

Public Const GC_RET_NOT_FOUND As String = "kT6XopQg2m" ' Term/ref not found in file

Public Const GC_RET_FILE_EMPTY As String = "hIn8vW2b8g" ' File contains no data

Public Const GC_RET_TDC_FILE_EMPTY As String = "k76fWAb1lB" ' TDC file contains no data

Public Const GC_RET_ALL_OK As String = "u7vO4Xs21l" ' All OK

Public Const GC_RET_NO_FIELDS As Integer = 1 ' Document has no (mail merge) fields/ no fields to update

Public Const GC_RET_DDS_ERROR As Integer = -1 ' Data Source has too few columns

Public Const GC_RET_UPDATE_ERROR As Integer = -2 ' Not used; reserved for later use

Public Const GC_RET_UPDATE_SUCCESS As Integer = 0 ' Successfully updated Data Source

' -------------------------------------------------Other Constants------------------------------------------------------

' Application.Width x Application.Height, xlMaximized, resolution 1280x1024:' 966x753 with taskbar 966x774 w/out taskbar -> Resize Factor ~1,325Public Const GC_DIV_PX_TO_DOT As Double = 1.325 ' e.g. 1280/966 = 1.32505, 1024/774 = 1.32300

Attribute VB_Name = "basBPPUSERmain"Option Explicit

' BPP_USER - Main Functons - Version v0.93a

'***********************************************'* *'* by Armin Laschet 01/2006 *'* for SAP Best Practices *'* [email protected] *'* *'***********************************************

Private dataFilesFolder As String

Private foundUsePersDataKey As BooleanPrivate usePersData As BooleanPrivate mustUpdateDataSource As BooleanPrivate connected As BooleanPrivate Const CMD_BAR_NAME As String = "Formatting"Private Const FIELDSBUTTONTAG As String = "SAPBP_DocuFieldsButton"

Sub AutoOpen()Dim i As Integer

' For i = ThisDocument.VBProject.References.Count To 1 Step -1' If ThisDocument.VBProject.References(i).IsBroken Then' ThisDocument.VBProject.References.Remove ThisDocument.VBProject.References(i)' End If' Next i

' NEW - 060515 ' Somehow, the Personalization Fields button is still visible in some documents Call uninstallFieldsInterface Application.ScreenUpdating = False connected = connectToDataSource 'sets "save" property to "false" ThisDocument.Saved = True Application.NormalTemplate.Saved = True Application.ScreenUpdating = True Application.DisplayAlerts = wdAlertsNone

End Sub

Sub uninstallFieldsInterface()Dim cb As CommandBarDim cbc As CommandBarControl For Each cb In CommandBars If cb.Name = CMD_BAR_NAME Then For Each cbc In cb.Controls If cbc.Tag = FIELDSBUTTONTAG Then cbc.Delete Exit Sub End If Next cbc End If Next cb

End Sub

Sub AutoClose()Dim tmp As Template For Each tmp In Application.Templates tmp.Saved = True Next ThisDocument.AttachedTemplate.Saved = TrueEnd Sub

Sub FileSave() ' overrides the default FileSave()

Application.NormalTemplate.Saved = True ThisDocument.AttachedTemplate.Saved = True ThisDocument.Save End Sub

Private Function connectToDataSource() As BooleanDim environmentFilePath As StringDim dataSourceName As String, envFileCont As VariantDim varDDS As Variant, updateState As Integer

'get path to environment file - if file doesn't exist, use default data source environmentFilePath = getEnvironmentFilePath(GC_FLN_TMP_ENVIRONMENTFILE) ' import environment file as array envFileCont = getFileContent2D(environmentFilePath) If Not IsArray(envFileCont) Then ' No access to environment file, file is empty or inconsistent -> Default data will be used ' Assuming, that document has never been used with personalized data, ' default data should be available, as that is how the document was saved on release Debug.Print "No access to environment file '" & environmentFilePath & "' or file is empty." connectToDataSource = False Exit Function End If ' Evaluate environment file: ' - Retrieve path to data source ' - Check whether the user wants to use default or personalized data ' - Check, whether the data source needs to be updated If evaluateEnvironmentFile(envFileCont) = False Then ' Can only be true End If ' Assuming that document has never been used with personalized data, ' default data should be available, as that is how the document was saved on release. ' Otherwise the fields will filled with the values on last save. If Not foundUsePersDataKey Then ' user hasn't yet personalized data -> use default data connectToDataSource = False Exit Function End If

If Not PathFileExists(dataFilesFolder) Then MsgBox "The folder with the external variants" & vbCr & _ "could not be retrieved from the environment file." & vbCr & _ "Potential causes:" & vbCr & _ " - The environment file is corrupt." & vbCr & _ " - The folder has been renamed/deleted." & vbCr & vbCr & _ "Create a new environment (file)" & vbCr & _ "with the Personalization Assistant.", vbExclamation, "Missing Data" connectToDataSource = False Exit Function End If

If usePersData = True Then ' user wants to use personalized data in documentation dataSourceName = AppendBackSlash(dataFilesFolder) & GC_FLN_DDS Else ' user wants to use default data in documentation dataSourceName = AppendBackSlash(dataFilesFolder) & GC_FLN_DDS_DEF End If

' check whether the data source file exists If Not PathFileExists(dataSourceName) Then If usePersData Then ' Personalized Data Source File not found ' 2do: ' Decide, how to handle this ' E.G.: Show info to user or just do silently the right thing, ' For now, we just create a new DDS

If updateDataSource(False, GC_FLN_TMP_ENVIRONMENTFILE, dataFilesFolder, dataFilesFolder) = False Then ' errors reported in function Debug.Print "Could not update data source(1)." connectToDataSource = False Exit Function Else ' DDS was created -> just keep on End If

Else ' Default Data Source File not found ' Use last saved values: ' No chance to retrieve default data, when doc was opened from a local/network drive. ' No problem, if doc was opened from DVD, 'cause last saved values are default anyway. Debug.Print "Could not find Default Data Source '" & dataSourceName & "'" connectToDataSource = False Exit Function End If ElseIf usePersData Then If mustUpdateDataSource Then ' Data Source is out of date If updateDataSource(False, GC_FLN_TMP_ENVIRONMENTFILE, dataFilesFolder, dataFilesFolder) = False Then ' errors reported in function Debug.Print "Could not update data source(2)." connectToDataSource = False Exit Function End If End If End If

' everything looks OK - connect to data source updateState = updateData(True, dataSourceName, varDDS) If updateState = GC_RET_DDS_ERROR Then Debug.Print "Data Source is empty or inconsistent" connectToDataSource = False ElseIf updateState = GC_RET_NO_FIELDS Then Debug.Print "No fields in BPP." connectToDataSource = False ElseIf updateState = GC_RET_UPDATE_SUCCESS Then connectToDataSource = True Else Debug.Print "Could not update fields in BPP." connectToDataSource = False End If

End Function

Function evaluateEnvironmentFile(ByVal envFileCont As Variant) As Boolean' searches for the entry TARGETFOLDERNAME in environmentFilePath,' which holds the path to the user defined folder(TargetFolder)' searches for the key UsePersDataInDocu and reads its valueDim row As Integer, foundUpdateDDSkey As Boolean

' Initialize global parameters dataFilesFolder = "" usePersData = False foundUsePersDataKey = False mustUpdateDataSource = False

For row = LBound(envFileCont, 2) To UBound(envFileCont, 2) If Trim(envFileCont(0, row)) = GC_KEY_ENVFILE_TARGETFOLDER Then dataFilesFolder = Trim(envFileCont(1, row)) ElseIf Trim(envFileCont(0, row)) = GC_KEY_ENVFILE_UPDATE_DDS Then If LCase(Trim(envFileCont(1, row))) = LCase(GC_VAL_FALSE) Then ' Value is GC_VAL_FALSE ' -> Do not update Data Source Else ' Value is anything else than GC_VAL_FALSE ' -> updateDDS mustUpdateDataSource = True End If foundUpdateDDSkey = True ElseIf Trim(envFileCont(0, row)) = GC_KEY_ENVFILE_USEPERSDATA Then If LCase(Trim(envFileCont(1, row))) = LCase(GC_VAL_FALSE) Then ' Value is GC_VAL_FALSE, no entry or false entry ' -> Do not use personalized data Else ' Value is anything else than GC_VAL_FALSE -> use personalized data usePersData = True End If foundUsePersDataKey = True End If Next row If Not foundUpdateDDSkey Then ' maybe it's an old kind of environment file w/o the updateDDS key -> update DDS Debug.Print "No 'UpdateDataSource' key." mustUpdateDataSource = True End If If foundUsePersDataKey = False Then Debug.Print "No 'UsePersData' key." End If evaluateEnvironmentFile = True End Function

Attribute VB_Name = "basBPPDataSource"Option Explicit

' BPP_USER - Data Source update functions for BPPs - Version v0.93a

' Indices of array varFieldsPrivate Const FLD_NAME As Integer = 0Private Const FLD_IDX As Integer = 1

Function updateData(ByVal calledByUSER As Boolean, ByVal dataSourceName As String, ByRef varDDS As Variant) As IntegerDim varFields As Variant, lngI As Long, lngJ As Long

varFields = getFields ' get all field names, values and field indices of this document If Not IsArray(varFields) Then ' document has no (mail merge) fields/ no fields to update updateData = GC_RET_NO_FIELDS If calledByUSER Then ' since DEV needs data anyway Exit Function End If End If

varDDS = getFileContent2Dunicode(dataSourceName) If Not IsArray(varDDS) Then ' no access to data source or data source is empty updateData = GC_RET_DDS_ERROR Exit Function End If If UBound(varDDS, 1) < GC_COL_DDS_LASTCOL Then ' data source has too few columns updateData = GC_RET_DDS_ERROR Exit Function End If If updateData = GC_RET_NO_FIELDS Then Exit Function ' DEV's got the data now -> exit here If updateFields(varFields, varDDS) = False Then ' can only be true ... for now updateData = GC_RET_UPDATE_ERROR Exit Function End If updateData = GC_RET_UPDATE_SUCCESS End Function

Function updateFields(ByRef varFields As Variant, ByRef varDDS As Variant) As BooleanDim lngHigh As Long, lngLow As LongDim docFld As Long, dataSrcFld As Long, idx As Long

Call quickSort2Dcols(varFields, 0, LBound(varFields, 2), UBound(varFields, 2)) ' sort this documents field names lngHigh = UBound(varDDS, 2) lngLow = LBound(varDDS, 2) Call quickSort2Dcols(varDDS, GC_COL_DDS_FLDNAME, lngLow, lngHigh) ' sort by data source by field names docFld = 0 dataSrcFld = 0 Do If LCase(varFields(FLD_NAME, docFld)) = LCase(varDDS(GC_COL_DDS_FLDNAME, dataSrcFld)) Then ' document field and data source field match idx = varFields(FLD_IDX, docFld) If ThisDocument.Fields(idx).Result varDDS(GC_COL_DDS_VALUE, dataSrcFld) And _ varDDS(GC_COL_DDS_VALUE, dataSrcFld) "" Then ' update value ThisDocument.Fields(idx).Result.Text = varDDS(GC_COL_DDS_VALUE, dataSrcFld) Do While docFld + 1