Beispiel #1
0
        public new void Dispose()
        {
            if (AutoFilter != null)
            {
                AutoFilter.Dispose();
            }

            base.Dispose();
        }
Beispiel #2
0
        private IAsset ReadFromSheet(Worksheet sheet)
        {
            // We need this sheet to be active so that we can access to its window via Application.ActiveWindow.
            sheet.Activate();
            var cells = new CellAccessor(sheet);

            // Find the header and data rows.
            int header_row, data_row;
            {
                AutoFilter auto_filter   = null;
                Window     active_window = null;
                if ((auto_filter = sheet.AutoFilter) != null)
                {
                    // This worksheet has an auto filter.
                    // Use the filter's header row (i.e., those with filter buttons) as the header,
                    // and the rows below it as the data.
                    header_row = auto_filter.Range.Row;
                    data_row   = header_row + 1;
                }
                else if ((active_window = sheet.Application.ActiveWindow).FreezePanes)
                {
                    // This worksheet has freeze panes.
                    // Use the last non-empty row on the frozen pane as the header,
                    // and the non-frozen rows as the data.
                    var r     = active_window.ScrollRow;
                    var panes = active_window.Panes;
                    for (int i = 1; i <= panes.Count; i++)
                    {
                        var pane = panes[i];
                        r = Math.Min(r, pane.ScrollRow + pane.VisibleRange.Rows.Count);
                    }
                    data_row = r;
                    while (--r > 1 && cells.IsRowEmpty(r))
                    {
                        ;
                    }
                    header_row = r;
                }
                else
                {
                    // Otherwise, use the first row as the header (even if it is totally empty),
                    // and the remainig rows as data.
                    header_row = 1;
                    data_row   = 2;
                }
                active_window?.Dispose();
                auto_filter?.Dispose();
            }

            // Fetch column headers on the first row.
            var headers = new string[cells.Columns + 1];

            for (int column = 1; column <= cells.Columns; column++)
            {
                var label = cells[header_row, column];
                headers[column] = string.IsNullOrWhiteSpace(label) ? null : label;
            }

            // Detect source and target languages.
            // We only consider visible cells for source and target language columns.
            string source_label = null, source_language = null;
            string target_label = null, target_language = null;

            for (int column = 1; column <= cells.Columns; column++)
            {
                if (cells.IsCellVisible(header_row, column))
                {
                    var lang = FindLanguageCode(headers[column]);
                    if (lang != null)
                    {
                        if (source_language == null)
                        {
                            // Assume the first language code represents the source language.
                            source_label    = headers[column];
                            source_language = lang;
                        }
                        else if (target_language == null && lang != source_language)
                        {
                            // Assume the second language code represents the target language.
                            target_label    = headers[column];
                            target_language = lang;
                            break;
                        }
                    }
                }
            }

            // Group columns into source, target, and other properties.
            var source_columns     = new List <int>();
            var target_columns     = new List <int>();
            var properties_columns = new List <int>();

            for (int column = 1; column <= cells.Columns; column++)
            {
                var label = headers[column];
                if (source_label?.Equals(label, StringComparison.InvariantCultureIgnoreCase) == true)
                {
                    source_columns.Add(column);
                }
                else if (target_label?.Equals(label, StringComparison.InvariantCultureIgnoreCase) == true)
                {
                    target_columns.Add(column);
                }
                else
                {
                    properties_columns.Add(column);
                }
            }

            // Detect duplicate header labels (i.e., property names)
            var duplicates = new HashSet <string>(headers.Where(h => h != null).GroupBy(h => h).Where(g => g.Count() > 1).Select(g => g.Key));

            // Modify header labels so that they are unique.
            // Note that the following modification could produce new ducplicates.
            // We don't go too strict, because this is just a nice-to-have feature.
            foreach (var column in properties_columns)
            {
                var label = headers[column];
                if (label == null)
                {
                    // No label.  Use Excel column name as a label.
                    headers[column] = cells.GetColumnName(column);
                }
                else if (duplicates.Contains(label))
                {
                    // Duplicate label.  Append the column name.
                    headers[column] = string.Format("{0} ({1})", label, cells.GetColumnName(column));
                }
                else
                {
                    // Already unique name.  Leave it alone.
                }
            }

            // Turn data rows into TransPairs.
            var pairs      = new List <ITransPair>(cells.Rows); // This capacity is just a rough standard.
            int serial     = 0;
            var sources    = new List <InlineString>(source_columns.Count);
            var targets    = new List <InlineString>(target_columns.Count);
            var properties = new List <string>(properties_columns.Count);

            for (int row = data_row; row <= cells.Rows; row++)
            {
                if (cells.IsRowEmpty(row))
                {
                    // Ignore an empty row.
                }
                else
                {
                    var visible = cells.IsRowVisible(row);
                    var id      = row.ToString();

                    // Collect source texts.
                    sources.Clear();
                    sources.AddRange(source_columns.Select(c => cells[row, c]).Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => new InlineString(s)));
                    if (sources.Count == 0)
                    {
                        sources.Add(InlineString.Empty);
                    }

                    // Collect target texts.
                    targets.Clear();
                    targets.AddRange(target_columns.Select(c => cells[row, c]).Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => new InlineString(s)));
                    if (targets.Count == 0)
                    {
                        targets.Add(InlineString.Empty);
                    }

                    // Collect property values.
                    properties.Clear();
                    properties.AddRange(properties_columns.Select(c => cells[row, c]));
                    int last = properties.Count - 1;
                    while (last > 0 && string.IsNullOrWhiteSpace(properties[last]))
                    {
                        --last;
                    }
                    if (last < properties.Count - 1)
                    {
                        properties.RemoveRange(last + 1, properties.Count - last - 1);
                    }
                    var properties_array = properties.Count > 0 ? properties.ToArray() : EMPTY_PROPERTY_VALUES;

                    // Create TransPairs.
                    // We allow multiple source and/or target texts in an Excel row,
                    // so we generate all possible source-target combinations.
                    foreach (var source in sources)
                    {
                        foreach (var target in targets)
                        {
                            pairs.Add(new ExcelGlossaryPair()
                            {
                                Serial         = visible ? ++serial : -1,
                                Id             = id,
                                Source         = source,
                                Target         = target,
                                SourceLang     = source_language,
                                TargetLang     = target_language,
                                PropertyValues = properties_array,
                            });
                        }
                    }
                }
            }
            if (pairs.Count == 0)
            {
                return(null);
            }
            pairs.TrimExcess();

            return(new ExcelGlossaryAsset()
            {
                Package = (sheet.Parent as Workbook)?.FullName,
                Original = sheet.Name,
                SourceLang = source_language,
                TargetLang = target_language,
                TransPairs = pairs,
                Properties = properties_columns.Select(column => new PropInfo(headers[column], false)).ToArray(),
            });
        }