private static string generateWorksheetName(
            PreparedInformation preparedInformation,
            FileGroup fileGroup,
            Project project)
        {
            // http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/84c0c4d2-52b9-4502-bece-fdc616db05f8

            const int maxLength = 31;

            var ni =
                (preparedInformation.UseCrypticExcelExportSheetNames
                    ? fileGroup.UniqueID.ToString()
                    : fileGroup.GetNameIntelligent(project))
                .Replace('\\', '#')
                .Replace('/', '#')
                .Replace('?', '_')
                .Replace('*', '_')
                .Replace('[', '_')
                .Replace(']', '_')
                .Replace(':', '_');
            //var cs = fileGroup.Checksum.ToString();

            //var s1 = string.Format( @" ({0})", cs );
            //var len = maxLength - s1.Length;

            var ni2 = FileGroup.ShortenFilePath(ni, maxLength);

            return(ni2);
        }
        /// <summary>
        /// Check whether the export of duplicates is enabled/disabled and then
        /// check whether was exported in the past.
        /// </summary>
        private static bool wasAlreadyExported(
            ICollection <string> exportedReferenceLanguageValues,
            PreparedInformation preparedInformation,
            IInheritedSettings parentSettings,
            DataRow row)
        {
            if (preparedInformation.EliminateDuplicateRows)
            {
                // Column 0=FileGroup checksum, column 1=Tag name.
                for (var columnIndex = 2; columnIndex < row.Table.Columns.Count; ++columnIndex)
                {
                    var languageCode =
                        IsFileName(row.Table.Columns[columnIndex].ColumnName)
                            ? new LanguageCodeDetection(preparedInformation.Project).DetectLanguageCodeFromFileName(
                            parentSettings,
                            row.Table.Columns[columnIndex].ColumnName)
                            : row.Table.Columns[columnIndex].ColumnName;

                    if (string.Compare(preparedInformation.ReferenceLanguageCode, languageCode,
                                       StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        var languageValue = ConvertHelper.ToString(row[columnIndex]);
                        return(exportedReferenceLanguageValues.Contains(languageValue));
                    }
                }

                return(false);
            }
            else
            {
                return(false);
            }
        }
        private static bool wantExportLanguageCode(
            PreparedInformation preparedInformation,
            string languageCode)
        {
            if (string.IsNullOrEmpty(languageCode))
            {
                return(false);
            }
            else
            {
                if (string.Compare(languageCode, preparedInformation.ReferenceLanguageCode,
                                   StringComparison.OrdinalIgnoreCase) == 0)
                {
                    return(true);
                }
                else
                {
                    // ReSharper disable LoopCanBeConvertedToQuery
                    foreach (var destinationLanguageCode in preparedInformation.DestinationLanguageCodes)
                    // ReSharper restore LoopCanBeConvertedToQuery
                    {
                        if (string.Compare(languageCode, destinationLanguageCode,
                                           StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            return(true);
                        }
                    }

                    return(false);
                }
            }
        }
        private static bool hasChangedTextSinceLastExport(
            SnapshotController ssc,
            PreparedInformation preparedInformation,
            IInheritedSettings settings,
            DataRow row)
        {
            var lcs = new List <string>(new[] { preparedInformation.ReferenceLanguageCode });

            for (var i = 0; i < lcs.Count; ++i)
            {
                lcs[i] = lcs[i].ToLowerInvariant();
            }

            // ReSharper disable LoopCanBeConvertedToQuery);
            foreach (DataColumn column in row.Table.Columns)
            // ReSharper restore LoopCanBeConvertedToQuery
            {
                // Column 0=FileGroup checksum, column 1=Tag name.
                if (column.Ordinal != 0 && column.Ordinal != 1 && !isCommentColumn(column))
                {
                    var languageCode =
                        IsFileName(column.ColumnName)
                            ? new LanguageCodeDetection(preparedInformation.Project).DetectLanguageCodeFromFileName(
                            settings,
                            column.ColumnName)
                            : column.ColumnName;
                    languageCode = languageCode.ToLowerInvariant();

                    if (/*lcs.Contains(languageCode.Substring(0, 2)) ||*/
                        lcs.Contains(languageCode))
                    {
                        var languageValue = ConvertHelper.ToString(row[column], string.Empty);
                        if (!StringExtensionMethods.IsNullOrWhiteSpace(languageValue))
                        {
                            var fileGroup = row[0] as string;
                            var tagName   = row[1] as string;
                            if (hasValueChanged(ssc, fileGroup, tagName, languageCode, languageValue))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
        private static DataTable removeUnusedColumns(
            PreparedInformation preparedInformation,
            IInheritedSettings settings,
            DataTable table)
        {
            var result = new DataTable();

            // --
            // Columns.

            // Order:
            // 1. The filegroup checksum column.
            // 2. The name column.
            // 3. The reference language column.
            // 4. All other columns.
            // 5. The comment column.

            // 1.
            result.Columns.Add(table.Columns[0].ColumnName, typeof(string));

            // 2.
            result.Columns.Add(table.Columns[1].ColumnName, typeof(string));

            // 3.
            foreach (DataColumn column in table.Columns)
            {
                // Column 0=FileGroup checksum, column 1=Tag name.
                if (column.Ordinal != 0 && column.Ordinal != 1)
                {
                    var languageCode =
                        IsFileName(column.ColumnName)
                            ? new LanguageCodeDetection(preparedInformation.Project).DetectLanguageCodeFromFileName(
                            settings,
                            column.ColumnName)
                            : column.ColumnName;

                    if (string.Compare(preparedInformation.ReferenceLanguageCode, languageCode,
                                       StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        result.Columns.Add(column.ColumnName);
                        break;
                    }
                }
            }

            // 4.
            foreach (DataColumn column in table.Columns)
            {
                // Column 0=FileGroup checksum, column 1=Tag name.
                if (column.Ordinal != 0 && column.Ordinal != 1)
                {
                    var languageCode =
                        IsFileName(column.ColumnName)
                            ? new LanguageCodeDetection(preparedInformation.Project).DetectLanguageCodeFromFileName(
                            settings,
                            column.ColumnName)
                            : column.ColumnName;

                    if (string.Compare(preparedInformation.ReferenceLanguageCode, languageCode,
                                       StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        if (wantExportLanguageCode(preparedInformation, languageCode))
                        {
                            result.Columns.Add(column.ColumnName);
                        }
                    }
                }
            }

            // 5.
            if (preparedInformation.ExportCommentColumn)
            {
                result.Columns.Add(table.Columns[table.Columns.Count - 1].ColumnName, typeof(string));
            }

            // --
            // Rows.

            foreach (DataRow sourceRow in table.Rows)
            {
                var destinationRow = result.NewRow();

                foreach (DataColumn column in result.Columns)
                {
                    destinationRow[column.ColumnName] = sourceRow[column.ColumnName];
                }

                result.Rows.Add(destinationRow);
            }

            // --

            return(result);
        }
        private static bool wantExportRow(
            SnapshotController ssc,
            PreparedInformation preparedInformation,
            IInheritedSettings settings,
            DataRow row,
            CommentVisibilityScope commentVisibilityScope)
        {
            if (FileGroup.IsCompleteRowEmpty(row) &&
                !preparedInformation.ExportCompletelyEmptyRows ||
                // http://www.codeproject.com/KB/aspnet/ZetaResourceEditor.aspx?msg=3367544#xx3367544xx)
                FileGroup.IsInternalRow(row))
            {
                return(false);
            }

            if (preparedInformation.OnlyExportRowsWithNoTranslation)
            {
                var emptyCount = 0;

                // ReSharper disable LoopCanBeConvertedToQuery
                foreach (DataColumn column in row.Table.Columns)
                // ReSharper restore LoopCanBeConvertedToQuery
                {
                    // Column 0=FileGroup checksum, column 1=Tag name.
                    if (column.Ordinal != 0 && column.Ordinal != 1 && !isCommentColumn(column))
                    {
                        var languageCode =
                            IsFileName(column.ColumnName)
                                ? new LanguageCodeDetection(preparedInformation.Project).DetectLanguageCodeFromFileName(
                                settings,
                                column.ColumnName)
                                : column.ColumnName;

                        if (string.Compare(languageCode, preparedInformation.ReferenceLanguageCode,
                                           StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            if (ConvertHelper.ToString(row[column], string.Empty).Trim().Length <= 0)
                            {
                                emptyCount++;
                            }
                        }
                    }
                }

                if (preparedInformation.Project.EnableExcelExportSnapshots)
                {
                    return(emptyCount > 0 ||
                           preparedInformation.OnlyExportRowsWithChangedTexts &&
                           hasChangedTextSinceLastExport(ssc, preparedInformation, settings, row));
                }
                else
                {
                    return(emptyCount > 0);
                }
            }
            else
            {
                if (preparedInformation.Project.EnableExcelExportSnapshots)
                {
                    return(!preparedInformation.OnlyExportRowsWithChangedTexts ||
                           hasChangedTextSinceLastExport(ssc, preparedInformation, settings, row));
                }
                else
                {
                    return(true);
                }
            }
        }
        private static void doProcess(
            PreparedInformation preparedInformation,
            BackgroundWorker bw,
            int fileGroupsLength,
            ICollection <string> savedFiles)
        {
            var ssc = new SnapshotController(preparedInformation.Project, @"XLS");

            ssc.Initialize();

            // --

            var exportedReferenceLanguageValues = new HashSet <string>();

            var dataSet = new DataSet();

            dataSet.Tables.Clear();

            DataTable dataTable       = null;
            var       currentRowIndex = 0;

            var suggestedWorkSheetNamesToRemove = new List <string>();

            var fileGroupIndex = 0;

            foreach (var fileGroup in preparedInformation.FileGroups)
            {
                if (bw.CancellationPending)
                {
                    throw new OperationCanceledException();
                }

                var isFirstFileGroup = fileGroupIndex == 0;
                var isLastFileGroup  = fileGroupIndex == preparedInformation.FileGroups.Length - 1;

                var worksheetIndex = -1;

                if (preparedInformation.ExportAllGroups)
                {
                    if (dataTable == null)
                    {
                        dataSet.Tables.Add();
                        worksheetIndex      = dataSet.Tables.Count - 1;
                        dataTable           = dataSet.Tables[worksheetIndex];
                        dataTable.TableName = Resources.SR_CommandProcessorSend_Process_ZRE_Export;
                    }
                }
                else
                {
                    dataSet.Tables.Add();
                    worksheetIndex      = dataSet.Tables.Count - 1;
                    dataTable           = dataSet.Tables[worksheetIndex];
                    dataTable.TableName = generateWorksheetName(preparedInformation, fileGroup, preparedInformation.Project);
                }

                var rows = dataTable.Rows;

                var wantNewSheet = !preparedInformation.ExportAllGroups || isFirstFileGroup;

                // --
                // Header.

                const int headerStartRowIndex = 0;
                const int columnStartIndex    = 0;

                if (wantNewSheet)
                {
                    if (preparedInformation.ExportFileGroupColumn)
                    {
                        // Checksum.
                        // 2014-06-25 Krickbaum - Corrected type to double
                        dataTable.Columns.Add(Resources.SR_CommandProcessorSend_Process_Group, typeof(double));
                    }
                    if (preparedInformation.ExportNameColumn)
                    {
                        // String name.
                        dataTable.Columns.Add(Resources.SR_CommandProcessorSend_Process_Name, typeof(string));
                    }
                    if (preparedInformation.ExportReferenceLanguageColumn)
                    {
                        // Reference language.
                        dataTable.Columns.Add(preparedInformation.ReferenceLanguageCode, typeof(string));
                    }

                    // Destination languages.
                    // ReSharper disable ForCanBeConvertedToForeach
                    for (var runningColIndex = 0;
                         // ReSharper restore ForCanBeConvertedToForeach
                         runningColIndex < preparedInformation.DestinationLanguageCodes.Length;
                         ++runningColIndex)
                    {
                        var destinationLanguageCode =
                            preparedInformation.DestinationLanguageCodes[runningColIndex];

                        if (string.Compare(preparedInformation.ReferenceLanguageCode, destinationLanguageCode,
                                           StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            dataTable.Columns.Add(destinationLanguageCode, typeof(string));
                        }
                    }

                    if (preparedInformation.ExportCommentColumn)
                    {
                        // String name.
                        dataTable.Columns.Add(Resources.SR_CommandProcessorSend_Process_Comment, typeof(string));
                    }

                    currentRowIndex = headerStartRowIndex;
                }

                // --
                // Content.

                var dp    = new DataProcessing(fileGroup);
                var table =
                    dp.GetDataTableFromResxFiles(preparedInformation.Project, preparedInformation.ExportCommentColumn);
                table =
                    removeUnusedColumns(
                        preparedInformation,
                        fileGroup.ParentSettings,
                        table);

                var rowIndex = 0;

                foreach (DataRow row in table.Rows)
                {
                    if ((rowIndex + 1) % 20 == 0)
                    {
                        bw.ReportProgress(
                            0,
                            new ExcelProgressInformation
                        {
                            TemporaryProgressMessage =
                                string.Format(
                                    Resources.SR_CommandProcessorSend_Process_ProcessingFileGroupOfRowOf,
                                    fileGroupIndex + 1,
                                    fileGroupsLength,
                                    rowIndex + 1,
                                    table.Rows.Count,
                                    (int)((rowIndex + 1.0) /
                                          table.Rows.Count *
                                          ((fileGroupIndex + 1.0) /
                                           fileGroupsLength) * 100))
                        });

                        if (bw.CancellationPending)
                        {
                            throw new OperationCanceledException();
                        }
                    }

                    if (wantExportRow(
                            ssc,
                            preparedInformation,
                            fileGroup.ParentSettings,
                            row,
                            CommentVisibilityScope.InMemory))
                    {
                        if (!wasAlreadyExported(
                                exportedReferenceLanguageValues,
                                preparedInformation,
                                fileGroup.ParentSettings,
                                row))
                        {
                            var offset = 0;

                            if (preparedInformation.ExportFileGroupColumn)
                            {
                                // Checksum.
                                checkEnsureRowPresent(dataTable, currentRowIndex);
                                rows[currentRowIndex][columnStartIndex] = fileGroup.GetChecksum(preparedInformation.Project);
                                makeCellReadOnly(dataTable.Columns[columnStartIndex]);
                                offset++;
                            }
                            if (preparedInformation.ExportNameColumn)
                            {
                                // String name.
                                checkEnsureRowPresent(dataTable, currentRowIndex);
                                rows[currentRowIndex][columnStartIndex + offset] = row[1]; // Column 0=FileGroup checksum, column 1=Tag name.
                                makeCellReadOnly(dataTable.Columns[columnStartIndex + offset]);

                                offset++;
                            }

                            var effectiveDestinationColumnIndex = 1;
                            // Column 0=FileGroup checksum, column 1=Tag name.
                            for (var sourceColumnIndex = 2;
                                 sourceColumnIndex < table.Columns.Count - (preparedInformation.ExportCommentColumn ? 1 : 0); // Subtract 1, because last column is ALWAYS the comment.
                                 ++sourceColumnIndex)
                            {
                                var languageValue = row[sourceColumnIndex] as string;
                                var languageCode  =
                                    IsFileName(table.Columns[sourceColumnIndex].ColumnName)
                                        ? new LanguageCodeDetection(preparedInformation.Project)
                                    .DetectLanguageCodeFromFileName(
                                        fileGroup.ParentSettings,
                                        table.Columns[sourceColumnIndex].ColumnName)
                                        : table.Columns[sourceColumnIndex].ColumnName;
                                var isReferenceLanguage =
                                    string.Compare(preparedInformation.ReferenceLanguageCode, languageCode,
                                                   StringComparison.OrdinalIgnoreCase) == 0;

                                if (isReferenceLanguage && preparedInformation.ExportReferenceLanguageColumn ||
                                    !isReferenceLanguage)
                                {
                                    checkEnsureRowPresent(dataTable, currentRowIndex);
                                    var columnIndex = columnStartIndex - 1 + effectiveDestinationColumnIndex + offset;
                                    rows[currentRowIndex][columnIndex] = languageValue;

                                    if (isReferenceLanguage)
                                    {
                                        makeCellReadOnly(dataTable.Columns[columnIndex]);

                                        exportedReferenceLanguageValues.Add(
                                            string.IsNullOrEmpty(languageValue)
                                                ? string.Empty
                                                : languageValue);
                                    }

                                    effectiveDestinationColumnIndex++;
                                }
                            }

                            if (preparedInformation.ExportCommentColumn)
                            {
                                // Comment.
                                checkEnsureRowPresent(dataTable, currentRowIndex);
                                rows[currentRowIndex][columnStartIndex - 1 + effectiveDestinationColumnIndex + offset]
                                    = DataProcessing.GetComment(preparedInformation.Project, row);

                                /*offset++;*/
                            }

                            currentRowIndex++;
                        }
                    }

                    // In every loop, check again.
                    suggestedWorkSheetNamesToRemove.Remove(dataTable.TableName);

                    //CHANGED if worksheet empty: remove it)
                    if (currentRowIndex == headerStartRowIndex + 1 &&
                        !preparedInformation.ExportAllGroups)
                    {
                        // http://www.codeproject.com/Messages/3539004/Export-to-Excel-bug.aspx
                        if (worksheetIndex < dataSet.Tables.Count)
                        {
                            suggestedWorkSheetNamesToRemove.Add(dataTable.TableName);
                        }
                    }

                    rowIndex++;
                }

                //dataTable.AutoFitRow(currentRowIndex - 1);

                if (bw.CancellationPending)
                {
                    throw new OperationCanceledException();
                }

                // --

                if (!preparedInformation.ExportAllGroups ||
                    isLastFileGroup)
                {
                    var offset = 0;

                    if (preparedInformation.ExportFileGroupColumn)
                    {
                        // Checksum.
                        //dataTable.AutoFitColumn(
                        //    columnStartIndex,
                        //    headerStartRowIndex,
                        //    currentRowIndex);
                        offset++;
                    }
                    if (preparedInformation.ExportNameColumn)
                    {
                        // String name.
                        //dataTable.AutoFitColumn(
                        //    columnStartIndex + offset,
                        //    headerStartRowIndex,
                        //    currentRowIndex);
                        offset++;
                    }
                    if (preparedInformation.ExportReferenceLanguageColumn)
                    {
                        // Reference language.
                        //dataTable.AutoFitColumn(
                        //    columnStartIndex + offset,
                        //    headerStartRowIndex,
                        //    currentRowIndex);
                        offset++;
                    }

                    // Destination languages.
                    int runningColIndex;
                    for (runningColIndex = 0;
                         runningColIndex < preparedInformation.DestinationLanguageCodes.Length;
                         ++runningColIndex)
                    {
                        //dataTable.AutoFitColumn(
                        //    columnStartIndex + runningColIndex + offset,
                        //    headerStartRowIndex,
                        //    currentRowIndex);
                    }

                    if (preparedInformation.ExportCommentColumn)
                    {
                        // Comment.
                        //dataTable.AutoFitColumn(
                        //    columnStartIndex + offset + runningColIndex,
                        //    headerStartRowIndex,
                        //    currentRowIndex);
                        /*offset++;*/
                    }
                }

                // --

                fileGroupIndex++;
            }

            // --

            // 2011-01-31, Uwe Keim.
            // http://www.codeproject.com/Messages/3559812/Export-error.aspx
            foreach (var name in suggestedWorkSheetNamesToRemove)
            {
                dataSet.Tables.Remove(name);
            }

            // --

            if (dataSet.Tables.Count > 0)
            {
                bw.ReportProgress(
                    0,
                    new ExcelProgressInformation
                {
                    TemporaryProgressMessage =
                        string.Format(
                            Resources.SR_CommandProcessorSend_Process_SavingMicrosoftOfficeExcelDocument)
                });

                savedFiles.Add(preparedInformation.DestinationFilePath);
                CoreExcelExporter.ExportToExcelFile(dataSet, preparedInformation.DestinationFilePath);
            }
            else
            {
                bw.ReportProgress(
                    0,
                    new ExcelProgressInformation
                {
                    TemporaryProgressMessage =
                        Resources.ExcelExportController_doProcess_Skipping_Microsoft_Office_Excel_document_,
                    WarningMessage =
                        string.Format(
                            Resources.ExcelExportController_doProcess_Skipping_Excel_document___0___because_it_contains_no_work_sheets_,
                            ZlpPathHelper.GetFileNameFromFilePath(preparedInformation.DestinationFilePath))
                });
            }

            // --

            // At very last, to not overwrite before comparing.
            if (preparedInformation.Project.EnableExcelExportSnapshots)
            {
                ssc.TakeFullSnapshot(
                    preparedInformation.FileGroups,
                    new[] { preparedInformation.ReferenceLanguageCode },
                    bw);
            }
        }